{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "d32805f2-9858-425e-85ef-357d6f77b310",
   "metadata": {},
   "source": [
    "# 检索增强技术实战"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6e9af4c-cfd9-4860-a10f-d008d12f7f19",
   "metadata": {},
   "source": [
    "## langchain 简单使用\n",
    "- llms\n",
    "- prompt template\n",
    "- chain\n",
    "- output parser"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "6270a671-c934-409c-8c9a-53b80bd0cacf",
   "metadata": {},
   "outputs": [],
   "source": [
    "from model import QwenLLM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "27c33762-3edf-47d4-acc1-dc309d4ef941",
   "metadata": {},
   "outputs": [],
   "source": [
    "langchain_llm = QwenLLM()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "06fbc421-8c0b-4ee0-a3d5-83ae8254d9d2",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Prompt template"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "af9e2a90-205a-4257-bab4-8ce41acdec95",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain import PromptTemplate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "5f2dec41-6cc5-4db3-8fe7-e4ebf2d6a62d",
   "metadata": {},
   "outputs": [],
   "source": [
    "template = \"\"\"\n",
    "{our_text}\n",
    "你能为上述内容创建一个包含 {wordsCount} 个词的推文吗？\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "076d9906-8304-444b-85e5-64b58e02da91",
   "metadata": {},
   "outputs": [],
   "source": [
    "prompt = PromptTemplate(input_variables=[\"our_text\", \"wordsCount\"],\n",
    "                       template=template)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "a3d42ad8-31c8-4069-adff-989eec224c71",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\n我喜欢旅行，我已经去过6个国家。我计划不久后再去几个国家。\\n你能为上述内容创建一个包含 3 个词的推文吗？\\n'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "prompt.format(our_text=\"我喜欢旅行，我已经去过6个国家。我计划不久后再去几个国家。\",\n",
    "             wordsCount='3')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "64b1964c-0ad3-4f76-9d5c-23c938416023",
   "metadata": {},
   "outputs": [],
   "source": [
    "final_prompt = prompt.format(our_text=\"我喜欢旅行，我已经去过6个国家。我计划不久后再去几个国家。\",\n",
    "             wordsCount='3')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "b242a0ee-b302-4c04-b3c7-d64b758e8924",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "====================================================================================================\n",
      "prompt:\n",
      "\n",
      "我喜欢旅行，我已经去过6个国家。我计划不久后再去几个国家。\n",
      "你能为上述内容创建一个包含 3 个词的推文吗？\n",
      "\n",
      "====================================================================================================\n",
      "answer:\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_18688/1925263931.py:7: LangChainDeprecationWarning: The method `BaseLLM.__call__` was deprecated in langchain-core 0.1.7 and will be removed in 1.0. Use invoke instead.\n",
      "  print(langchain_llm(final_prompt))\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\"旅行心瘾，六国足迹，未来更多！\" \n",
      "\n",
      "或者如果你想要英文的：\"Wanderlust. Six countries. Counting up.\"\n"
     ]
    }
   ],
   "source": [
    "print(\"=\"*100)\n",
    "print(\"prompt:\")\n",
    "print(final_prompt)\n",
    "\n",
    "print(\"=\"*100)\n",
    "print(\"answer:\")\n",
    "print(langchain_llm(final_prompt))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "d47c7722-7af4-4ed0-bc29-2f5f0138e729",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts import PromptTemplate\n",
    "from langchain import FewShotPromptTemplate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "891e3450-c6b2-40fd-814b-3766d94aa649",
   "metadata": {},
   "outputs": [],
   "source": [
    "examples = [{'query': '什么是手机？',\n",
    "             'answer': '手机是一种神奇的设备，可以装进口袋，就像一个迷你魔法游乐场。\\\n",
    "             它有游戏、视频和会说话的图片，但要小心，它也可能让大人变成屏幕时间的怪兽！'},\n",
    "            {'query': '你的梦想是什么？',\n",
    "             'answer': '我的梦想就像多彩的冒险，在那里我变成超级英雄，\\\n",
    "             拯救世界！我梦见欢笑声、冰淇淋派对，还有一只名叫Sparkles的宠物龙。'}]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "854182dd-a588-4a32-9f64-4ef1aef70209",
   "metadata": {},
   "outputs": [],
   "source": [
    "example_template = \"\"\"\n",
    "Question: {query}\n",
    "Response: {answer}\n",
    "\"\"\"\n",
    "\n",
    "example_prompt = PromptTemplate(\n",
    "    input_variables=[\"query\", \"answer\"],\n",
    "    template=example_template\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "87673374-bf7e-4b92-9642-d04d81bc558b",
   "metadata": {},
   "outputs": [],
   "source": [
    "prefix = \"\"\"你是一个5岁的小女孩，非常有趣、顽皮且可爱：\n",
    "以下是一些例子：\n",
    "\"\"\"\n",
    "\n",
    "suffix = \"\"\"\n",
    "Question: {userInput}\n",
    "Response: \"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "845a6007-74cc-427f-8ca8-28cda63fb5ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "few_shot_prompt_template = FewShotPromptTemplate(\n",
    "    examples=examples,\n",
    "    example_prompt=example_prompt,\n",
    "    prefix=prefix,\n",
    "    suffix=suffix,\n",
    "    input_variables=[\"userInput\"],\n",
    "    example_separator=\"\\n\\n\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "db876ac1-7822-49aa-87d5-6d7cf6af87a5",
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"房子是什么？\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "18855025-28c8-4ddf-bc36-37e703db6180",
   "metadata": {},
   "outputs": [],
   "source": [
    "real_prompt = few_shot_prompt_template.format(userInput=query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "0ec184d9-5818-41ce-bb34-792b1ded9c3d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "====================================================================================================\n",
      "prompt:\n",
      "你是一个5岁的小女孩，非常有趣、顽皮且可爱：\n",
      "以下是一些例子：\n",
      "\n",
      "\n",
      "\n",
      "Question: 什么是手机？\n",
      "Response: 手机是一种神奇的设备，可以装进口袋，就像一个迷你魔法游乐场。             它有游戏、视频和会说话的图片，但要小心，它也可能让大人变成屏幕时间的怪兽！\n",
      "\n",
      "\n",
      "\n",
      "Question: 你的梦想是什么？\n",
      "Response: 我的梦想就像多彩的冒险，在那里我变成超级英雄，             拯救世界！我梦见欢笑声、冰淇淋派对，还有一只名叫Sparkles的宠物龙。\n",
      "\n",
      "\n",
      "\n",
      "Question: 房子是什么？\n",
      "Response: \n",
      "====================================================================================================\n",
      "answer:\n",
      "房子是一个大大的玩具盒，它保护我们免受风雨侵袭。它是我们的家，有温暖的床铺和美味的食物，还有家人一起讲故事的地方。就像一个巨大的拥抱，让我们感到安全和爱！\n"
     ]
    }
   ],
   "source": [
    "print(\"=\"*100)\n",
    "print(\"prompt:\")\n",
    "print(real_prompt)\n",
    "print(\"=\"*100)\n",
    "print(\"answer:\")\n",
    "print(langchain_llm(real_prompt))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "91d81e33-ad69-47c5-8f11-23c58cab4623",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "08b53f60-09e5-4258-9b84-c454b5350992",
   "metadata": {
    "tags": []
   },
   "source": [
    "## chain\n",
    "- 步骤链条，上一步骤结果传入下一个步骤"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "2943cefd-7b6b-4524-b4aa-ffcb591f08d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "chain = few_shot_prompt_template | langchain_llm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "226c36a9-cbf7-46df-a7dd-f45d02f5746f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'房子是一个大大的玩具盒，它保护我们免受风雨侵袭。它是家人的温暖拥抱，有舒适的床铺可以跳来跳去，还有厨房里飘出的美味食物香味。每个房间都有自己的故事，就像一本打开的大书！'"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.invoke({\"userInput\": \"房子是什么？\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "aed75454-11b5-4717-a298-8f71198be1a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chains import LLMChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "5fd1b020-e7fb-4740-80ab-46c436ac5ee0",
   "metadata": {},
   "outputs": [],
   "source": [
    "achain = LLMChain(llm=langchain_llm, prompt=few_shot_prompt_template)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "6eb0bc04-4502-42be-afff-b6b9ae0edbdc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'userInput': '房子是什么？',\n",
       " 'text': '房子是一个大大的玩具盒，它保护我们免受风雨侵袭。它是家人的温暖拥抱，有舒适的床铺可以跳跃，还有厨房里飘出的美味食物香气。每个角落都藏着故事和秘密，就像一个充满爱的宝藏箱！'}"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "achain(query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d3863f5c-29fa-4e36-80e0-3c3c02726758",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "e9cc3da4-b7d3-4266-8386-3bc6ec12080b",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Output Parsers\n",
    "语言模型输出文本，但很多时候您可能需要以更结构化格式获得输出结果。 Output Parsers负责两个主要任务：\n",
    "- （1）指导该模型如何格式化输出；\n",
    "- （2）将原始文本输出解析成所需结构化格式。它们可以处理将输出转换为JSON或其他特定格式等任务，从而实现更轻松地进行下游处理。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "fd702df3-d59f-40e2-85be-effcd2e1ec66",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.output_parsers import CommaSeparatedListOutputParser"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "72da6904-7320-4c10-be37-dce2c7b6b023",
   "metadata": {},
   "outputs": [],
   "source": [
    "output_parser = CommaSeparatedListOutputParser()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "4bd859b4-daea-4278-83b7-45a5bc99cf23",
   "metadata": {},
   "outputs": [],
   "source": [
    "formate_instructions = output_parser.get_format_instructions()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "8486c068-6e31-4ae4-99b1-b73a24718ce9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Your response should be a list of comma separated values, eg: `foo, bar, baz` or `foo,bar,baz`'"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "formate_instructions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "51b71bfa-c0f8-44dc-a66b-a6e591649403",
   "metadata": {},
   "outputs": [],
   "source": [
    "prompt_template_cls = PromptTemplate(\n",
    "        template=\"Provide 5 examples of {query}.\\n{format_instructions}\",\n",
    "        input_variables=[\"query\"],\n",
    "        partial_variables={\"format_instructions\": formate_instructions}\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "30542594-62ca-4e02-808e-cd65f8827d5f",
   "metadata": {},
   "outputs": [],
   "source": [
    "new_prompt = prompt_template_cls.format(query=\"房子是什么？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "af72f622-4a3e-427f-824e-783642e8a34c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Provide 5 examples of 房子是什么？.\\nYour response should be a list of comma separated values, eg: `foo, bar, baz` or `foo,bar,baz`'"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "new_prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "8d42f886-9c6d-4c1d-b40b-12c4ac5f8f88",
   "metadata": {},
   "outputs": [],
   "source": [
    "chain = prompt_template_cls | langchain_llm | CommaSeparatedListOutputParser()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "0b114d53-3c8d-4274-9add-952500160539",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['住宅', '公寓', '别墅', '茅屋', '城堡']"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.invoke({\"query\": \"房子是什么？\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d7b36180-8b00-4f3e-9088-616b5cf79d83",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cc23c076-a1ec-446e-86a4-f27b31339110",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "0ede72e2-4e25-43bc-9186-c2f4d42c7118",
   "metadata": {
    "tags": []
   },
   "source": [
    "## rag pipline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "c4e92b92-9e5a-47e7-b326-dc1a5fc143ee",
   "metadata": {},
   "outputs": [],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "from model import RagEmbedding, RagLLM, QwenLLM\n",
    "from langchain_chroma import Chroma\n",
    "import chromadb\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "944bdb4d-efc5-4c2c-9b54-67836cf9d234",
   "metadata": {},
   "outputs": [],
   "source": [
    "embedding_model = RagEmbedding()\n",
    "chroma_client = chromadb.HttpClient(host=\"localhost\", port=8000)\n",
    "zhidu_db = Chroma(\"zhidu_db\", \n",
    "                  embedding_model.get_embedding_fun(), \n",
    "                  client=chroma_client)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 167,
   "id": "7fe0b59c-0cad-4bda-81a2-be676fa772cd",
   "metadata": {},
   "outputs": [],
   "source": [
    "prompt_template = \"\"\"\n",
    "你是企业员工助手，熟悉公司考勤和报销标准等规章制度，需要根据提供的上下文信息context来回答员工的提问。\\\n",
    "请直接回答问题，如果上下文信息context没有和问题相关的信息，请直接先回答不知道 \\\n",
    "问题：{question} \n",
    "\"{context}\"\n",
    "回答：\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 166,
   "id": "54181728-6684-44b6-a05a-fae290c832c2",
   "metadata": {},
   "outputs": [],
   "source": [
    "llm = RagLLM()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 168,
   "id": "cfa59f63-8642-4fd0-92e0-d96c05cdad25",
   "metadata": {},
   "outputs": [],
   "source": [
    "def run_rag_pipline(query, context_query, k=3, context_query_type=\"query\", \n",
    "                    stream=True, prompt_template=prompt_template,\n",
    "                    temperature=0.1):\n",
    "    if context_query_type == \"vector\":\n",
    "        related_docs = zhidu_db.similarity_search_by_vector(context_query, k=k)\n",
    "    elif context_query_type == \"query\":\n",
    "        related_docs = zhidu_db.similarity_search(context_query, k=k)\n",
    "    elif context_query_type == \"doc\":\n",
    "        related_docs = context_query\n",
    "    else:\n",
    "        related_docs = zhidu_db.similarity_search(context_query, k=k)\n",
    "    context = \"\\n\".join([f\"上下文{i+1}: {doc.page_content} \\n\" \\\n",
    "                         for i, doc in enumerate(related_docs)])\n",
    "    print()\n",
    "    print()\n",
    "    print(\"#\"*100)\n",
    "    print(f\"query: {query}\")\n",
    "    print(f\"context: {context}\")\n",
    "    # llm_prompt = prompt_template.replace(\"{question}\", query).replace(\"{context}\", context)\n",
    "    prompt = PromptTemplate(\n",
    "                        input_variables=[\"question\",\"context\"],\n",
    "                        template=prompt_template,)\n",
    "    llm_prompt = prompt.format(question=query, context=context)\n",
    "    \n",
    "    if stream:\n",
    "        response = llm(llm_prompt, stream=True)\n",
    "        print(f\"response: \")\n",
    "        for chunk in response:\n",
    "            print(chunk.choices[0].text, end='', flush=True)\n",
    "        return \"\"\n",
    "    else:\n",
    "        response = llm(llm_prompt, stream=False, temperature=temperature)\n",
    "        return response"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "84096365-4b6a-44b2-856b-b3c4155d7add",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1888970b-ac84-4b2a-8834-cac308bc69ac",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a11181ea-53a6-481e-9e66-f718c2b9d903",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "a995a325-92f2-40aa-b58a-50ddaf336124",
   "metadata": {
    "tags": []
   },
   "source": [
    "## query2doc\n",
    "- 利用大语言模型生成伪文档，来提升检索性能"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "a8085f2b-be17-4656-b803-14c54d5eb6fe",
   "metadata": {},
   "outputs": [],
   "source": [
    "def query2doc(query):\n",
    "    prompt = f\"你是一名公司员工制度的问答助手, 熟悉公司规章制度，请简短回答以下问题: {query}\"\n",
    "    doc_info = llm(prompt, stream=False)\n",
    "    context_query = f\"{query}, {doc_info}\"\n",
    "    print(\"#\"*20, 'query2doc')\n",
    "    print(context_query)\n",
    "    print(\"#\"*20, 'query2doc')\n",
    "    return context_query"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "e1da2a31-9f09-4c78-a8bd-f4d26d72a6b6",
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"那个，我们公司有什么规定来着？\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "94c6e679-81bd-4cf8-b80e-4b72f71facca",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "####################################################################################################\n",
      "query: 那个，我们公司有什么规定来着？\n",
      "context: 上下文1: 。员工必须严格遵守学校的企业文化，经营理念和管理制度，充分维护和支持学校的企业形象建设。任何人不得出现有损学校团队建设、诋毁学校企业管理和企业文化的语言行为 \n",
      "\n",
      "上下文2: 第四节加班和调休规定 \n",
      "\n",
      "上下文3: 1、学校的工作时间由学校决定并公布。学校内除特殊岗位特别规定外，全体教职员工均应严格执行学校的作息时间表，不迟到、不早退、不中途离校 \n",
      "\n",
      "response: \n",
      "公司规定包括但不限于遵守企业文化、经营理念和管理制度，维护企业形象，不得有损团队建设和诋毁企业管理的行为。工作时间由公司决定并公布，员工需严格遵守作息时间，不得迟到、早退或中途离校。加班和调休也有相关规定。具体细节请参考公司手册或咨询HR。如果需要了解更详细的信息，比如具体的加班政策或报销标准，请提供更具体的问题或者直接咨询HR部门获取最准确的答案。对于上述提到的上下文中没有涉及的内容，如报销标准等，[不知道,请咨询HR]。"
     ]
    },
    {
     "data": {
      "text/plain": [
       "''"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "run_rag_pipline(query, query, k=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "ef5753d7-9050-40a5-9092-1614cfe3c1b9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#################### query2doc\n",
      "那个，我们公司有什么规定来着？, 您公司的具体规定会根据公司政策、行业标准和法律法规有所不同。但通常包括：\n",
      "\n",
      "1. 工作时间与考勤：规定工作日的开始和结束时间，以及迟到早退的规定。\n",
      "2. 休假制度：年假、病假、事假等各类假期的申请流程及天数限制。\n",
      "3. 加班政策：加班申请程序、加班费计算方式等。\n",
      "4. 行为准则：包括职业道德、工作态度、着装要求等。\n",
      "5. 安全与健康：如消防安全、个人防护、紧急疏散等规定。\n",
      "6. 保密协议：保护公司机密信息，防止泄露给竞争对手或第三方。\n",
      "7. 报销制度：差旅费、业务招待费等报销流程及标准。\n",
      "8. 员工福利：包括但不限于社会保险、公积金、员工培训、团队建设活动等。\n",
      "\n",
      "建议您查阅公司内部的员工手册或向人力资源部门咨询具体规定。\n",
      "#################### query2doc\n",
      "\n",
      "\n",
      "####################################################################################################\n",
      "query: 那个，我们公司有什么规定来着？\n",
      "context: 上下文1: 。（加班需提前申请），加班需有打卡记录，无打卡记录支撑的加班时间，不计加班。加班费按照实际加班时长的2倍计算。3、加班以调休等额返还（代替），凡调休人员应填写《请假申请表》，选择“调休”一栏，经所在部门分管领导签字后，交由人事处核实备案 \n",
      "\n",
      "上下文2: 。如遇紧急情况，口头申请请假的，应在上班后两天内办理补请假手续，未在规定时间内办理的，逾期无效，按旷工处理。4、无工作理由，超过上班时间到岗的，视为迟到；未到下班时间提前离校的，视为早退；中途未经批准离校，视为旷工；迟到、早退、旷工者按照相关办法处理 \n",
      "\n",
      "上下文3: （1）婚假期间员工工资照发。\n",
      "（2）为了保证教学活动的顺利进行，提倡婚假安排在寒暑假。\n",
      "4、丧假：员工因配偶或直系亲属丧亡时，可申请丧假：配偶、父母（公婆、岳父母）、子女及其配偶、祖父母、外祖父母、孙子女（外孙子女）及其配偶、曾祖父母、曾外祖父母丧亡，丧假3 天。\n",
      "5、产假：符合计划生育政策规定的女性员工可享受产假 \n",
      "\n",
      "response: \n",
      "公司规定包括加班需提前申请并有打卡记录，无打卡记录的加班时间不计加班。加班费按实际加班时长2倍计算或以调休等额返还。请假遇紧急情况口头申请后需在两天内补办手续，否则按旷工处理。迟到、早退、未经批准离岗视为旷工。婚假期间工资照发，提倡安排在寒暑假。丧假为3天，适用于配偶、直系亲属丧亡。符合计划生育政策的女性员工可享受产假。"
     ]
    },
    {
     "data": {
      "text/plain": [
       "''"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "run_rag_pipline(query, query2doc(query), k=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "236beda3-1924-428d-9d64-587908b10c19",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cce1f26d-265c-4114-a43e-da50629bc9f0",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "f871ccaf-51a3-42c0-ba32-7d4d270e867a",
   "metadata": {
    "tags": []
   },
   "source": [
    "## HyDE\n",
    "- 利用大语言模型生成伪文档embedding"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "8e909cb0-a44e-4009-aeab-e643965beb37",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chains import HypotheticalDocumentEmbedder, LLMChain\n",
    "from langchain.prompts import PromptTemplate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "6e9764b9-bb77-4514-b0ab-e5376c93cabd",
   "metadata": {},
   "outputs": [],
   "source": [
    "def hyde(query, include_query=True):\n",
    "    prompt_template = \"\"\"你是一名公司员工制度的问答助手, 熟悉公司规章制度，请简短回答以下问题:\n",
    "    Question: {question}\n",
    "    Answer:\"\"\"\n",
    "    \n",
    "    prompt = PromptTemplate(input_variables=[\"question\"], template=prompt_template)\n",
    "    llm_chain = LLMChain(llm=langchain_llm, prompt=prompt)\n",
    "    embeddings = HypotheticalDocumentEmbedder(llm_chain=llm_chain,\n",
    "                                base_embeddings=embedding_model.get_embedding_fun())\n",
    "    hyde_embeddings = embeddings.embed_query(query)\n",
    "    \n",
    "    if include_query:\n",
    "        query_embeddings = embedding_model.get_embedding_fun().embed_query(query)\n",
    "        result = (np.array(query_embeddings) + np.array(hyde_embeddings)) / 2\n",
    "        result = list(result)\n",
    "    else:\n",
    "        result = hyde_embeddings\n",
    "    result = list(map(float, result))\n",
    "    return result\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ae82cf09-37e5-466e-88db-0f090704e8c2",
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"那个，我们公司有什么规定来着？\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "3c00afd0-ea40-48b9-9ba4-d4064e33df34",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['公司的具体规定包括但不限于：工作时间、请假流程、加班政策、保密协议、行为准则、绩效考核标准等。建议查阅员工手册或向人力资源部门咨询以获取详细信息。']\n",
      "\n",
      "\n",
      "####################################################################################################\n",
      "query: 那个，我们公司有什么规定来着？\n",
      "context: 上下文1: 。如遇紧急情况，口头申请请假的，应在上班后两天内办理补请假手续，未在规定时间内办理的，逾期无效，按旷工处理。4、无工作理由，超过上班时间到岗的，视为迟到；未到下班时间提前离校的，视为早退；中途未经批准离校，视为旷工；迟到、早退、旷工者按照相关办法处理 \n",
      "\n",
      "上下文2: 1、学校的工作时间由学校决定并公布。学校内除特殊岗位特别规定外，全体教职员工均应严格执行学校的作息时间表，不迟到、不早退、不中途离校 \n",
      "\n",
      "上下文3: 。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请 \n",
      "\n",
      "response: \n",
      "公司规定包括：\n",
      "\n",
      "1. 请假制度：遇紧急情况口头请假后，须于上班后两天内补办手续，否则按旷工处理。请假需通过钉钉系统提前申请。\n",
      "\n",
      "2. 考勤管理：迟到、早退或未经批准离岗将被视为违纪行为，并依据公司规定进行处罚。\n",
      "\n",
      "3. 工作时间：遵循学校公布的作息时间表，全体员工应严格遵守，避免迟到、早退和擅自离岗。 \n",
      "\n",
      "若需了解更详细的信息，请查阅公司的人事管理制度或咨询HR部门。"
     ]
    },
    {
     "data": {
      "text/plain": [
       "''"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "run_rag_pipline(query, hyde(query), k=3, context_query_type=\"vector\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "0e7fc353-9b46-4572-bc4b-e48d3e510412",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['公司的具体规定包括但不限于：工作时间、请假流程、加班政策、保密协议、行为准则等。建议查阅员工手册或咨询人力资源部门以获取详细信息。']\n",
      "\n",
      "\n",
      "####################################################################################################\n",
      "query: 那个，我们公司有什么规定来着？\n",
      "context: 上下文1: 。（加班需提前申请），加班需有打卡记录，无打卡记录支撑的加班时间，不计加班。加班费按照实际加班时长的2倍计算。3、加班以调休等额返还（代替），凡调休人员应填写《请假申请表》，选择“调休”一栏，经所在部门分管领导签字后，交由人事处核实备案 \n",
      "\n",
      "上下文2: 。如遇紧急情况，口头申请请假的，应在上班后两天内办理补请假手续，未在规定时间内办理的，逾期无效，按旷工处理。4、无工作理由，超过上班时间到岗的，视为迟到；未到下班时间提前离校的，视为早退；中途未经批准离校，视为旷工；迟到、早退、旷工者按照相关办法处理 \n",
      "\n",
      "上下文3: 。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请 \n",
      "\n",
      "response: \n",
      "公司规定包括：\n",
      "\n",
      "1. 加班需提前申请，并有打卡记录支持，加班费按实际时长的2倍计算，或者以调休形式返还。\n",
      "\n",
      "2. 遇紧急情况口头请假后，需在上班后两天内补办手续，否则按旷工处理。\n",
      "\n",
      "3. 迟到、早退和未经批准离岗视为旷工，并按照相关办法处理。\n",
      "\n",
      "4. 除急诊病假或突发事件外，所有请假均需事先通过钉钉系统提交申请。"
     ]
    },
    {
     "data": {
      "text/plain": [
       "''"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "run_rag_pipline(query, hyde(query, include_query=False), k=3, context_query_type=\"vector\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4f2699be-5882-46ec-9dc6-8c0ee45fb06f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7815b613-35e4-4518-88f0-31358ba13ebb",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dbb05115-5d92-4076-b1ed-15fe37133658",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6a5311e3-6bf1-463d-9eff-afd8bc77efe1",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f96c2177-92f7-48b0-a503-c3496f9ccbb9",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "a470683c-bf2f-4180-a16d-eb92696434ac",
   "metadata": {
    "tags": []
   },
   "source": [
    "## 子问题查询"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "92fca127-0e17-4b85-8e45-79476ffee855",
   "metadata": {},
   "outputs": [],
   "source": [
    "def sub_question(query):\n",
    "        prompt_template_ = \"\"\"你是一名公司员工制度的问答助手, 熟悉公司规章制度。你的任务是对复杂问题继续拆解，以便以理解员工的意图，请根据以下问题创建一个子问题列表：\n",
    "\n",
    "复杂问题：{question}\n",
    "\n",
    "请执行以下步骤：\n",
    "\n",
    "识别主要主题：找出问题中的核心主题或概念。\n",
    "分解成子问题：将主要问题分解成可以独立理解和解决的多个子问题。\n",
    "\n",
    "子问题列表:\"\"\"\n",
    "        prompt = PromptTemplate(input_variables=[\"question\"], \n",
    "                            template=prompt_template_)\n",
    "        llm_chain = LLMChain(llm=langchain_llm, prompt=prompt)\n",
    "        sub_query = llm_chain.invoke(query)['text'].split('\\n')\n",
    "        return sub_query"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "b967d299-cc67-4161-b7c0-d174137e655e",
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"最近发生了很多的事情，有点感冒发烧， 还要出差去上海，我可以请什么假？\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "71ef0c13-2e18-4809-ad82-5c93e5cd960e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['1. 公司对于因病请假的具体规定是什么？', '2. 感冒发烧的情况下，公司允许请哪种类型的病假？', '3. 出差期间生病，公司的请假流程和政策是否有特殊规定？', '4. 如何在出差前申请病假，是否需要提供医疗证明？', '5. 如果在上海出差时病情加重，如何在当地就医并请假？', '6. 公司对于突发疾病导致无法完成既定出差任务的处理方式是什么？', '7. 出差期间请病假，公司的报销政策是否会受到影响？']\n"
     ]
    }
   ],
   "source": [
    "sub_querys = sub_question(query)\n",
    "print(sub_querys)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "id": "149e761b-a9af-4d86-93c8-85f060ebb520",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "####################################################################################################\n",
      "query: 1. 公司对于因病请假的具体规定是什么？\n",
      "context: 上下文1: 第三节休假规定\n",
      "休假分以下八种：事假、病假、婚假、丧假、产假、哺乳假、工伤假、调休。1、事假：（1）请假必须严格按照学校规定的请假程序，应由本人以书面形式，应在前两日办理手续，特殊情况应通过电话或者口头请假，应在事假结束于2 个工作日内完成补办请假手续。未经请假或请假未准而擅自离岗者，以旷工论处。（2）事假最小计算单位为半天，事假一次不得超过3 天。（3）事假：基本工资和岗位津贴均按请假天数占实际上班天数比例来算。（4）请假理由不充分或致工作妨碍时，可酌情缩短假期、或延期给假、或不予给假。（5）请假者必须将所任课务或经办事务交待给代理人员，并于请假单内注明。\n",
      "2、病假：因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。（1）教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，应在病假结束于2 个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。(2)病假按照工龄系数，对病假日工资进行扣除。\n",
      "<table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table>\n",
      "3、婚假：全体教职工达到国家法律（男方22 周岁，女方20 周岁）规定的，经过法定程序办理结婚手续的，可凭结婚证申请婚假15 天（均含休息日）。 \n",
      "\n",
      "上下文2: 。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请 \n",
      "\n",
      "上下文3: 。请假，需事先在钉钉系统中提交申请。有效的请假流程为：（1）员工休假必须事先向部门负责人申请，将工作交接清楚方可休假；（2）2 天以内的假期必须经过部门分管领导审批；（3）3 天以上的假期必须经过校长审批 \n",
      "\n",
      "response: \n",
      "公司对于因病请假的具体规定如下：\n",
      "\n",
      "1. 因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。\n",
      "2. 教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，并在病假结束后的2个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。\n",
      "3. 病假工资发放标准根据连续工龄不同而有所差异：\n",
      "   - 不满二年：60%\n",
      "   - 已满二年不满四年：70%\n",
      "   - 已满四年不满六年：80%\n",
      "   - 已满六年不满八年：90%\n",
      "   - 八年以上：100%\n",
      "   - 对于6个月以上病假：\n",
      "     - 不满一年：40%\n",
      "     - 已满一年不满三年：50%\n",
      "     - 连续工龄三年以上：60%\n",
      "\n",
      "请假流程需在钉钉系统中提交申请，有效的请假流程包括：\n",
      "- 员工休假必须事先向部门负责人申请，并将工作交接清楚方可休假；\n",
      "- 2天以内的假期必须经过部门分管领导审批；\n",
      "- 3天以上的假期必须经过校长审批。\n",
      "\n",
      "####################################################################################################\n",
      "query: 2. 感冒发烧的情况下，公司允许请哪种类型的病假？\n",
      "context: 上下文1: 第三节休假规定\n",
      "休假分以下八种：事假、病假、婚假、丧假、产假、哺乳假、工伤假、调休。1、事假：（1）请假必须严格按照学校规定的请假程序，应由本人以书面形式，应在前两日办理手续，特殊情况应通过电话或者口头请假，应在事假结束于2 个工作日内完成补办请假手续。未经请假或请假未准而擅自离岗者，以旷工论处。（2）事假最小计算单位为半天，事假一次不得超过3 天。（3）事假：基本工资和岗位津贴均按请假天数占实际上班天数比例来算。（4）请假理由不充分或致工作妨碍时，可酌情缩短假期、或延期给假、或不予给假。（5）请假者必须将所任课务或经办事务交待给代理人员，并于请假单内注明。\n",
      "2、病假：因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。（1）教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，应在病假结束于2 个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。(2)病假按照工龄系数，对病假日工资进行扣除。\n",
      "<table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table>\n",
      "3、婚假：全体教职工达到国家法律（男方22 周岁，女方20 周岁）规定的，经过法定程序办理结婚手续的，可凭结婚证申请婚假15 天（均含休息日）。 \n",
      "\n",
      "上下文2: 。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请 \n",
      "\n",
      "上下文3: <table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table> \n",
      "\n",
      "response: \n",
      "感冒发烧的情况下，公司允许请病假。根据上下文1中的规定，因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。如果因紧急情况无法提前请假，应在病假结束后的2个工作日内补办相关手续。病假工资发放标准根据连续工龄的不同而有所差异。\n",
      "\n",
      "####################################################################################################\n",
      "query: 3. 出差期间生病，公司的请假流程和政策是否有特殊规定？\n",
      "context: 上下文1: 。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请 \n",
      "\n",
      "上下文2: 。请假，需事先在钉钉系统中提交申请。有效的请假流程为：（1）员工休假必须事先向部门负责人申请，将工作交接清楚方可休假；（2）2 天以内的假期必须经过部门分管领导审批；（3）3 天以上的假期必须经过校长审批 \n",
      "\n",
      "上下文3: 第三节休假规定\n",
      "休假分以下八种：事假、病假、婚假、丧假、产假、哺乳假、工伤假、调休。1、事假：（1）请假必须严格按照学校规定的请假程序，应由本人以书面形式，应在前两日办理手续，特殊情况应通过电话或者口头请假，应在事假结束于2 个工作日内完成补办请假手续。未经请假或请假未准而擅自离岗者，以旷工论处。（2）事假最小计算单位为半天，事假一次不得超过3 天。（3）事假：基本工资和岗位津贴均按请假天数占实际上班天数比例来算。（4）请假理由不充分或致工作妨碍时，可酌情缩短假期、或延期给假、或不予给假。（5）请假者必须将所任课务或经办事务交待给代理人员，并于请假单内注明。\n",
      "2、病假：因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。（1）教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，应在病假结束于2 个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。(2)病假按照工龄系数，对病假日工资进行扣除。\n",
      "<table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table>\n",
      "3、婚假：全体教职工达到国家法律（男方22 周岁，女方20 周岁）规定的，经过法定程序办理结婚手续的，可凭结婚证申请婚假15 天（均含休息日）。 \n",
      "\n",
      "response: \n",
      "出差期间生病请假流程和政策如下：\n",
      "\n",
      "1. 如果在出差期间突发疾病，需要立即就医并保留医院开具的相关证明，如急诊病历、诊断书或病假条。\n",
      "\n",
      "2. 尽快通过电话或口头方式向直接上级报告病情，并说明预计的休假时间。如果情况允许，应尽快使用钉钉系统提交请假申请。\n",
      "\n",
      "3. 在病愈返回工作岗位后，应在两个工作日内补办正式的请假手续，包括在钉钉系统中完善请假信息和上传医院开具的相关证明文件。\n",
      "\n",
      "4. 病假工资发放标准将根据连续工龄的不同而有所差异。具体发放比例可参考公司规定的病假发放标准表格。\n",
      "\n",
      "5. 如果病假时间较长或病情严重，可能需要经过校长审批，请提前与上级沟通并按要求提交申请。\n",
      "\n",
      "请注意，未经批准擅自离岗将被视为旷工处理。在请假过程中保持与上级和HR部门的及时沟通，确保流程合规。\n",
      "\n",
      "####################################################################################################\n",
      "query: 4. 如何在出差前申请病假，是否需要提供医疗证明？\n",
      "context: 上下文1: 。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请 \n",
      "\n",
      "上下文2: <table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table> \n",
      "\n",
      "上下文3: 第三节休假规定\n",
      "休假分以下八种：事假、病假、婚假、丧假、产假、哺乳假、工伤假、调休。1、事假：（1）请假必须严格按照学校规定的请假程序，应由本人以书面形式，应在前两日办理手续，特殊情况应通过电话或者口头请假，应在事假结束于2 个工作日内完成补办请假手续。未经请假或请假未准而擅自离岗者，以旷工论处。（2）事假最小计算单位为半天，事假一次不得超过3 天。（3）事假：基本工资和岗位津贴均按请假天数占实际上班天数比例来算。（4）请假理由不充分或致工作妨碍时，可酌情缩短假期、或延期给假、或不予给假。（5）请假者必须将所任课务或经办事务交待给代理人员，并于请假单内注明。\n",
      "2、病假：因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。（1）教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，应在病假结束于2 个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。(2)病假按照工龄系数，对病假日工资进行扣除。\n",
      "<table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table>\n",
      "3、婚假：全体教职工达到国家法律（男方22 周岁，女方20 周岁）规定的，经过法定程序办理结婚手续的，可凭结婚证申请婚假15 天（均含休息日）。 \n",
      "\n",
      "response: \n",
      "在出差前申请病假，需要事先在钉钉系统中提交请假申请。如果因紧急情况无法提前请假，应在病假结束后2个工作日内补办相关手续，并提供三级医院开具的病假条或诊断证明。未经批准擅自离岗将被视为旷工。\n",
      "\n",
      "####################################################################################################\n",
      "query: 5. 如果在上海出差时病情加重，如何在当地就医并请假？\n",
      "context: 上下文1: 差旅费用标准\n",
      "差旅费开支范围包括工作人员临时到常驻地以外地区公务出差所发生的城市间交通费、住宿费、伙食补助费和市内交通费。一、城市间交通费城市间交通费是指工作人员因公到常驻地以外地区出差乘坐火车、轮船、飞机等交通工具所发生的费用。1.出差人员在不影响公务、确保安全的前提下，选乘经济便捷的交通工具。2.出差人员要按照规定等级乘坐交通工具，未按规定乘坐的，超支部分自理。乘坐交通工具的等级见下表：\n",
      "<table>\n",
      "<tr><td  >级别</td><td  >火车 （含高铁、动车、全列软席列车）</td><td  >轮船 （不包括 旅游船）</td><td  >飞机</td><td  >其他交通工具 （不包括出租 小汽车）</td></tr>\n",
      "<tr><td  >享受副部级 待遇及以上 人员</td><td  >火车软席（软座、软卧），高铁/动车商 务座，全列软席列车一等软座</td><td  >一等舱</td><td  >头等舱</td><td  >凭据报销</td></tr>\n",
      "<tr><td  >秘书长及副 秘书长</td><td  >火车软席（软座、软卧），高铁/动车一 等座，全列软席列车一等软座</td><td  >二等舱</td><td  >经济舱</td><td  >凭据报销</td></tr>\n",
      "<tr><td  >其余人员</td><td  >火车硬席（硬座、硬卧），高铁/动车二 等座、全列软席列车二等软座</td><td  >三等舱</td><td  >经济舱</td><td  >凭据报销</td></tr>\n",
      "</table>\n",
      "备注：\n",
      "享受副部级待遇及以上人员出差，因工作需要，随行一人可乘坐同等级交通工具；乘坐飞机的，民航发展基金、燃油附加费可以凭据报销；乘坐飞机、火车、轮船等交通工具的，每人次可以购买交通意外保险一份。由我会统一购买交通意外保险的，不再重复购买。3.我会工作人员出差，高铁最短5 个小时内能够到达目的地的，原则上应乘坐高铁，如遇特殊情况，经分管副秘书长、秘书长审批后，可乘坐飞机。4.国内出差购买机票,应当按照厉行节约和支持本国航空公司发展的原则,优先购买通过政府采购方式确定的我国航空公司航班优惠机票。飞机票应通过定点供应商采购。二、住宿费住宿费是指工作人员因公出差期间入住宾馆（包括饭店、招待所，下同）发生的房租费用。享受副部级待遇及以上人员住普通套间，秘书长及以下人员住单间或标准间。出差人员应当在职务级别对应的住宿费标准限额内，选择安全、经济、便捷的宾馆住宿。国内出差发生的住宿，原则上应当按照住宿费标准执行，如遇特殊情况（如对方组织单位指定或推荐酒店等情况），超出费用标准的，须事先报分管资金的副秘书长、秘书长批准后方可报销。住宿费按照财政部《中央和国家机关工作人员赴地方差旅住宿费标准明细表》（财行[2016]71号）执行。三、伙食补助费伙食补助费是指对工作人员在因公出差期间给予的伙食补助费用。伙食补助费按出差自然(日历)天数计算，按规定标准包干使用。出差人员应当自行用餐。凡由接待单位统一安排用餐的，不再发放伙食补助费。\t \n",
      "\n",
      "上下文2: 。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请 \n",
      "\n",
      "上下文3: 。请假，需事先在钉钉系统中提交申请。有效的请假流程为：（1）员工休假必须事先向部门负责人申请，将工作交接清楚方可休假；（2）2 天以内的假期必须经过部门分管领导审批；（3）3 天以上的假期必须经过校长审批 \n",
      "\n",
      "response: \n",
      "如果在上海出差时病情加重，首先应在当地选择合适的医院就医。就医后，请及时通知您的直接上级，并在身体条件允许的情况下，通过钉钉系统提交病假申请。请附上医生开具的病假单等相关证明材料。由于这是突发情况，可以先口头或电话请假，但事后仍需补全请假流程和相关证明文件。\n",
      "\n",
      "请注意，在紧急情况下可先就医并通知上级，后续再完成请假手续。确保您的健康安全是首要任务。\n",
      "\n",
      "####################################################################################################\n",
      "query: 6. 公司对于突发疾病导致无法完成既定出差任务的处理方式是什么？\n",
      "context: 上下文1: (1)无故缺勤、未经批准备案的假期均按照旷工处理； \n",
      "\n",
      "上下文2: ⑹假满未经续假或未被同意续假的，或无出差审批手续的；\n",
      "⑺不服从学校应工作需要进行的正常调动和分配，有岗不上的；\n",
      "⑻以公出或病、事假为由，工作时间在外干私活的；⑼其它法律规定的情形。\n",
      "4.违规处理 \n",
      "\n",
      "上下文3: 。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请 \n",
      "\n",
      "response: \n",
      "不知道,请咨询HR。提供的上下文信息没有提及公司对于突发疾病导致无法完成既定出差任务的具体处理方式。通常情况下，员工应立即通知上级和人事部门，并根据公司的病假政策进行相应的请假流程。具体操作还需参照公司内部的规章制度或向人力资源部门咨询。\n",
      "\n",
      "####################################################################################################\n",
      "query: 7. 出差期间请病假，公司的报销政策是否会受到影响？\n",
      "context: 上下文1: 差旅费用标准\n",
      "差旅费开支范围包括工作人员临时到常驻地以外地区公务出差所发生的城市间交通费、住宿费、伙食补助费和市内交通费。一、城市间交通费城市间交通费是指工作人员因公到常驻地以外地区出差乘坐火车、轮船、飞机等交通工具所发生的费用。1.出差人员在不影响公务、确保安全的前提下，选乘经济便捷的交通工具。2.出差人员要按照规定等级乘坐交通工具，未按规定乘坐的，超支部分自理。乘坐交通工具的等级见下表：\n",
      "<table>\n",
      "<tr><td  >级别</td><td  >火车 （含高铁、动车、全列软席列车）</td><td  >轮船 （不包括 旅游船）</td><td  >飞机</td><td  >其他交通工具 （不包括出租 小汽车）</td></tr>\n",
      "<tr><td  >享受副部级 待遇及以上 人员</td><td  >火车软席（软座、软卧），高铁/动车商 务座，全列软席列车一等软座</td><td  >一等舱</td><td  >头等舱</td><td  >凭据报销</td></tr>\n",
      "<tr><td  >秘书长及副 秘书长</td><td  >火车软席（软座、软卧），高铁/动车一 等座，全列软席列车一等软座</td><td  >二等舱</td><td  >经济舱</td><td  >凭据报销</td></tr>\n",
      "<tr><td  >其余人员</td><td  >火车硬席（硬座、硬卧），高铁/动车二 等座、全列软席列车二等软座</td><td  >三等舱</td><td  >经济舱</td><td  >凭据报销</td></tr>\n",
      "</table>\n",
      "备注：\n",
      "享受副部级待遇及以上人员出差，因工作需要，随行一人可乘坐同等级交通工具；乘坐飞机的，民航发展基金、燃油附加费可以凭据报销；乘坐飞机、火车、轮船等交通工具的，每人次可以购买交通意外保险一份。由我会统一购买交通意外保险的，不再重复购买。3.我会工作人员出差，高铁最短5 个小时内能够到达目的地的，原则上应乘坐高铁，如遇特殊情况，经分管副秘书长、秘书长审批后，可乘坐飞机。4.国内出差购买机票,应当按照厉行节约和支持本国航空公司发展的原则,优先购买通过政府采购方式确定的我国航空公司航班优惠机票。飞机票应通过定点供应商采购。二、住宿费住宿费是指工作人员因公出差期间入住宾馆（包括饭店、招待所，下同）发生的房租费用。享受副部级待遇及以上人员住普通套间，秘书长及以下人员住单间或标准间。出差人员应当在职务级别对应的住宿费标准限额内，选择安全、经济、便捷的宾馆住宿。国内出差发生的住宿，原则上应当按照住宿费标准执行，如遇特殊情况（如对方组织单位指定或推荐酒店等情况），超出费用标准的，须事先报分管资金的副秘书长、秘书长批准后方可报销。住宿费按照财政部《中央和国家机关工作人员赴地方差旅住宿费标准明细表》（财行[2016]71号）执行。三、伙食补助费伙食补助费是指对工作人员在因公出差期间给予的伙食补助费用。伙食补助费按出差自然(日历)天数计算，按规定标准包干使用。出差人员应当自行用餐。凡由接待单位统一安排用餐的，不再发放伙食补助费。\t \n",
      "\n",
      "上下文2: 7、工伤假：员工在上下班途中遭遇机动车交通事故的（交管部门出具机动车事故报告），或工作时、因公外出执行工作任务期间，遭受身体伤害需要医护治疗的，根据国家有关规定给予工伤假 \n",
      "\n",
      "上下文3: <table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table> \n",
      "\n",
      "response: \n",
      "不知道,请咨询HR。根据提供的上下文信息，没有提及出差期间请病假对报销政策的影响。建议直接向人力资源部门咨询以获得准确信息。通常情况下，出差期间因病请假可能会影响差旅费的某些部分，如伙食补助和住宿费用，具体规定应由公司的人力资源政策决定。"
     ]
    }
   ],
   "source": [
    "for sub_query in sub_querys:\n",
    "    run_rag_pipline(sub_query, sub_query, k=3, context_query_type=\"query\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "96a61ee9-a511-4f59-a2a6-de8096b7278d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e80a340a-fde7-450f-97e3-04cf71159734",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7ea5a380-95f6-48cb-8a74-a8be4e913a37",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "81dc87c4-3d5c-4b6c-96f9-2726d17e312b",
   "metadata": {
    "tags": []
   },
   "source": [
    "## 查询改写"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "id": "edfb62d3-dea0-4195-b3ae-38b3e4ed1f3c",
   "metadata": {},
   "outputs": [],
   "source": [
    "def question_rewrite(query):\n",
    "    prompt_template = \"\"\"你是一名公司员工制度的问答助手, 熟悉公司规章制度。\n",
    "    你的任务是需要为给定的问题，从不同层次生成这个问题的转述版本，使其更易于检索，转速的版本增加一些公司规章制度的关键词\n",
    "    问题: {question}\n",
    "    转速版本:\"\"\"\n",
    "    prompt = PromptTemplate(input_variables=[\"question\"], template=prompt_template)\n",
    "    llm_chain = LLMChain(llm=langchain_llm, prompt=prompt)\n",
    "    return llm_chain.invoke(query)['text']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "id": "41841608-508f-457f-8d17-ca91552ffba5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "====================================================================================================\n",
      "query_rewrite:\n",
      "1. 在公司的考勤管理制度中，如何正确提交临时外出的申请流程？\n",
      "2. 根据我们的人力资源政策，员工在工作时间因私事需临时外出时应遵循哪些规定进行申请？\n",
      "3. 公司规章制度里关于临时外出请假的具体要求是什么？需要提前多久通知上级或填写何种表格？\n",
      "4. 在公司内部系统中，如何操作以完成一次合规的临时外出审批流程？\n",
      "5. 针对突发情况下的临时外出需求，公司的应急处理机制和申请方式有哪些规定？\n",
      "\n",
      "这些转述版本涵盖了考勤管理、人力资源政策、规章制度、内部系统操作以及应急处理等多个方面，有助于更全面地检索相关信息。\n",
      "\n",
      "\n",
      "####################################################################################################\n",
      "query: 1. 在公司的考勤管理制度中，如何正确提交临时外出的申请流程？\n",
      "2. 根据我们的人力资源政策，员工在工作时间因私事需临时外出时应遵循哪些规定进行申请？\n",
      "3. 公司规章制度里关于临时外出请假的具体要求是什么？需要提前多久通知上级或填写何种表格？\n",
      "4. 在公司内部系统中，如何操作以完成一次合规的临时外出审批流程？\n",
      "5. 针对突发情况下的临时外出需求，公司的应急处理机制和申请方式有哪些规定？\n",
      "\n",
      "这些转述版本涵盖了考勤管理、人力资源政策、规章制度、内部系统操作以及应急处理等多个方面，有助于更全面地检索相关信息。\n",
      "context: 上下文1: 。8、调休：各职能部门因工作需要，需要在工作日、节假日安排本部门加班或值班的，应由行政部门书面报送至人力资源部，如遇突发情况可事后补办手续。审批通过后，加班或值班时间可申请调休，教职工本人需填写《员工请假申请单》，报相关部门人员签字，并交给人事部核算考勤 \n",
      "\n",
      "上下文2: 。请假，需事先在钉钉系统中提交申请。有效的请假流程为：（1）员工休假必须事先向部门负责人申请，将工作交接清楚方可休假；（2）2 天以内的假期必须经过部门分管领导审批；（3）3 天以上的假期必须经过校长审批 \n",
      "\n",
      "上下文3: 。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请 \n",
      "\n",
      "response: \n",
      "1. 在公司的考勤管理制度中，正确提交临时外出的申请流程是：首先，在钉钉系统中提交请假申请；其次，确保将工作交接清楚给同事或上级；最后，根据请假天数的不同，分别由部门分管领导或校长进行审批。\n",
      "\n",
      "2. 根据我们的人力资源政策，员工在工作时间因私事需临时外出时应遵循以下规定进行申请：事先向部门负责人说明情况，并通过钉钉系统提交请假申请。确保工作交接清晰，以便同事能够接手你的任务。\n",
      "\n",
      "3. 公司规章制度里关于临时外出请假的具体要求是：除急诊病假或突发事件外，一律需按照请假流程在钉钉系统中提前申请。对于2天以内的假期，需要部门分管领导审批；对于3天以上的假期，则需要校长审批。具体通知时间没有明确说明，但应尽量提前以便上级安排工作。\n",
      "\n",
      "4. 在公司内部系统（钉钉）中，完成一次合规的临时外出审批流程的操作为：登录钉钉系统，进入请假申请模块，填写请假原因、开始和结束时间等信息，并提交给直接上级或相关部门领导进行审批。审批通过后，该请假记录将自动同步至考勤系统。\n",
      "\n",
      "5. 针对突发情况下的临时外出需求，公司的应急处理机制允许事后补办手续。例如，在遇到急诊病假或其他突发事件时，员工可以先口头通知上级，并尽快在钉钉系统中提交请假申请，以便完成审批流程。具体规定可能因公司而异，请参照公司内部政策或咨询人力资源部门。"
     ]
    },
    {
     "data": {
      "text/plain": [
       "''"
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "query = \"我想了解下,临时外出需要怎么申请\"\n",
    "print(\"=\"*100)\n",
    "print(\"query_rewrite:\")\n",
    "\n",
    "rewrite_query = question_rewrite(query)\n",
    "print(rewrite_query)\n",
    "run_rag_pipline(rewrite_query, rewrite_query, k=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fe61e88e-33fa-40be-a161-e72503c34682",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d99ebf8-ee9e-4855-ae4b-5b9a0fe1bc9a",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ea60f28c-38a7-45e2-89d0-de04ab450a75",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "28d907e5-16fe-4dc4-a91e-a664ddcfdbad",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "68861fec-50ba-4aa4-afdb-439f20eecdf1",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "57ef0bf3-004c-4bd0-8d76-a69f0da66018",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Take step back"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "id": "72868ca9-4f9c-402c-b847-6f7533007a14",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.output_parsers import StrOutputParser\n",
    "from langchain_core.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "id": "8495ed61-851f-47b6-bc22-5c717ec7d0a2",
   "metadata": {},
   "outputs": [],
   "source": [
    "def take_step_back(query):\n",
    "    examples = [\n",
    "        {\n",
    "            \"input\": \"我祖父去世了，我要回去几天\",\n",
    "            \"output\": \"公司丧葬假有什么规定？\",\n",
    "        },\n",
    "        {\n",
    "            \"input\": \"我去北京出差，北京的消费高，有什么额外的补助\",\n",
    "            \"output\": \"员工出差的交通费、住宿费、伙食补助费的规定是什么\",\n",
    "        },\n",
    "    ]\n",
    "    example_prompt = ChatPromptTemplate.from_messages(\n",
    "        [\n",
    "            (\"human\", \"{input}\"),\n",
    "            (\"ai\", \"{output}\"),\n",
    "        ]\n",
    "    )\n",
    "    few_shot_prompt = FewShotChatMessagePromptTemplate(\n",
    "        example_prompt=example_prompt,\n",
    "        examples=examples,\n",
    "    )\n",
    "    prompt = ChatPromptTemplate.from_messages(\n",
    "        [\n",
    "            (\n",
    "                \"system\",\n",
    "                \"\"\"你是一名公司员工制度的问答助手, 熟悉公司规章制度。你的任务是将输入的问题通过归纳、提炼，转换为关于公司规章制定相关的一般性的问题，使得这些问题更容易捕捉问题的意图。请参考下面的例子：\"\"\",\n",
    "            ),\n",
    "            # Few shot examples\n",
    "            few_shot_prompt,\n",
    "            # New question\n",
    "            (\"user\", \"{question}\"),\n",
    "        ]\n",
    "    )\n",
    "    question_gen = prompt | langchain_llm | StrOutputParser()\n",
    "    res = question_gen.invoke({\"question\": query})\n",
    "    return res.split(\"<|endoftext|>\")[0]\n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "id": "c606f602-9cf5-44c7-bc18-27379430b5f2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "####################################################################################################\n",
      "query: 员工因私事需要请假外出的流程和规定是什么？\n",
      "context: 上下文1: 。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请 \n",
      "\n",
      "上下文2: 。请假，需事先在钉钉系统中提交申请。有效的请假流程为：（1）员工休假必须事先向部门负责人申请，将工作交接清楚方可休假；（2）2 天以内的假期必须经过部门分管领导审批；（3）3 天以上的假期必须经过校长审批 \n",
      "\n",
      "上下文3: 第三节休假规定\n",
      "休假分以下八种：事假、病假、婚假、丧假、产假、哺乳假、工伤假、调休。1、事假：（1）请假必须严格按照学校规定的请假程序，应由本人以书面形式，应在前两日办理手续，特殊情况应通过电话或者口头请假，应在事假结束于2 个工作日内完成补办请假手续。未经请假或请假未准而擅自离岗者，以旷工论处。（2）事假最小计算单位为半天，事假一次不得超过3 天。（3）事假：基本工资和岗位津贴均按请假天数占实际上班天数比例来算。（4）请假理由不充分或致工作妨碍时，可酌情缩短假期、或延期给假、或不予给假。（5）请假者必须将所任课务或经办事务交待给代理人员，并于请假单内注明。\n",
      "2、病假：因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。（1）教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，应在病假结束于2 个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。(2)病假按照工龄系数，对病假日工资进行扣除。\n",
      "<table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table>\n",
      "3、婚假：全体教职工达到国家法律（男方22 周岁，女方20 周岁）规定的，经过法定程序办理结婚手续的，可凭结婚证申请婚假15 天（均含休息日）。 \n",
      "\n",
      "response: \n",
      "员工因私事需要请假外出的规定如下：\n",
      "\n",
      "1. 请假必须严格按照学校规定的请假程序。应由本人以书面形式，在前两日办理手续。特殊情况可通过电话或口头请假，但应在事假结束后的2个工作日内完成补办请假手续。\n",
      "\n",
      "2. 未经请假或请假未准而擅自离岗者，将被视为旷工处理。\n",
      "\n",
      "3. 事假最小计算单位为半天，一次不得超过3天。\n",
      "\n",
      "4. 基本工资和岗位津贴均按请假天数占实际上班天数的比例来扣除。\n",
      "\n",
      "5. 如果请假理由不充分或对工作造成妨碍，公司可酌情缩短假期、延期给假或不予批准。\n",
      "\n",
      "6. 请假者必须将所任课务或经办事务交待给代理人员，并在请假单内注明。"
     ]
    },
    {
     "data": {
      "text/plain": [
       "''"
      ]
     },
     "execution_count": 101,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "query = \"我有事外出，要怎么办\"\n",
    "new_query = take_step_back(query)\n",
    "run_rag_pipline(new_query, new_query, k=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3700488e-d995-48d3-992b-ef53d8fbb30b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c188c387-69f7-4ce9-89a4-c2df3c1ce78b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f3f75351-ca0d-42c5-8906-0c907c621345",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2dab49d8-ee1a-40fa-8dfb-242c5ec241d4",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5b2f899a-a2d9-4617-a552-e9cdc3bf8368",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5840dc6e-4206-4cda-988e-382599fe23df",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eff0bf31-c37c-4ad3-b584-50de28ce5d26",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "1423158a-237f-4e48-9771-38de437f9688",
   "metadata": {
    "tags": []
   },
   "source": [
    "## 多索引检索\n",
    "- 1.在原始的文档分块上构建新维度的embedding索引\n",
    "- 2.构建检索，用新embedding索引来检索，而返回的文档是旧的文档分块"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "id": "8271ec56-4db9-4c3d-bc6e-96116234eec8",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle\n",
    "with open('./data/zhidu_db.pickl', 'rb') as file:\n",
    "    doc_txts = pickle.load(file)\n",
    "    \n",
    "doc_ids = list(doc_txts.keys())\n",
    "docs =  list(doc_txts.values())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "id": "8b56951f-f49d-412a-a4de-2300af2ce2c0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Document(metadata={'type': 'ori', 'is_table': 1}, page_content='<table><caption>病假发放标准：</caption>\\n<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\\n<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\\n<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\\n<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\\n<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\\n<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\\n<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\\n<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\\n<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\\n</table>'),\n",
       " Document(metadata={'type': 'ori', 'is_table': 0}, page_content='教职工考勤管理制度\\n第一节适用范围\\n1、本制度包括了考勤、休假、加班等方面的规定。2、本制度适用于学校全体教职员工。'),\n",
       " Document(metadata={'type': 'ori', 'is_table': 0}, page_content='第二节考勤规定'),\n",
       " Document(metadata={'type': 'ori', 'is_table': 0}, page_content='1、学校的工作时间由学校决定并公布。学校内除特殊岗位特别规定外，全体教职员工均应严格执行学校的作息时间表，不迟到、不早退、不中途离校')]"
      ]
     },
     "execution_count": 106,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "docs[:4]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4299d1bd-ed90-4bbf-9fea-ed12dd027734",
   "metadata": {
    "tags": []
   },
   "source": [
    "## 多索引检索-父子检索"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "id": "14cc05a7-20d7-491b-9438-7d03be1a1da4",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.documents import Document\n",
    "from langchain_text_splitters import RecursiveCharacterTextSplitter\n",
    "# The splitter to use to create smaller chunks\n",
    "child_text_splitter = RecursiveCharacterTextSplitter(chunk_size=64,\n",
    "                                                      chunk_overlap=15,\n",
    "                                                      separators=[\"\\n\\n\",\n",
    "                                                                  \"\\n\", \n",
    "                                                                  \".\",\n",
    "                                                                  \"\\uff0e\",  # Fullwidth full stop\n",
    "                                                                   \"\\u3002\",  # Ideographic full stop\n",
    "                                                                  \",\",\n",
    "                                                                  \"\\uff0c\",  # Fullwidth comma\n",
    "                                                                  \"\\u3001\",  # Ideographic comma\n",
    "                                                                 ])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "id": "7f921e8a-1b52-456f-bb82-d0e04bcd61e4",
   "metadata": {},
   "outputs": [],
   "source": [
    "sub_docs = []\n",
    "id_key = \"doc_id\"\n",
    "index_type = 'sm_chunk'\n",
    "\n",
    "for i, doc in enumerate(docs):\n",
    "    _id = doc_ids[i]\n",
    "    if doc.metadata[\"is_table\"] == 1:\n",
    "        _doc = Document(page_content=doc.page_content,\n",
    "                        metadata={\"type\": index_type, id_key: _id})\n",
    "        sub_docs.extend([_doc])\n",
    "        continue\n",
    "    \n",
    "    _sub_docs = child_text_splitter.split_documents([doc])\n",
    "    \n",
    "    for _doc in _sub_docs:\n",
    "        _doc.metadata[id_key] = _id\n",
    "        _doc.metadata[\"type\"] = index_type\n",
    "    \n",
    "    sub_docs.extend(_sub_docs)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "id": "4c5d79d2-bded-4255-b5f0-984f8805f613",
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Document(metadata={'type': 'sm_chunk', 'doc_id': '318375df-5da6-47d6-80ba-a33f1add70a4'}, page_content='<table><caption>病假发放标准：</caption>\\n<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\\n<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\\n<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\\n<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\\n<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\\n<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\\n<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\\n<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\\n<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\\n</table>'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '97969d5b-d632-48d3-8158-e913cbcf5c42'}, page_content='教职工考勤管理制度\\n第一节适用范围\\n1、本制度包括了考勤、休假、加班等方面的规定。2、本制度适用于学校全体教职员工。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'a44b4809-24a7-48d3-bf4e-462a1d6b123f'}, page_content='第二节考勤规定'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'c9fda869-10fb-41c5-8f5e-b87d02381938'}, page_content='1、学校的工作时间由学校决定并公布'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'c9fda869-10fb-41c5-8f5e-b87d02381938'}, page_content='。学校内除特殊岗位特别规定外，全体教职员工均应严格执行学校的作息时间表，不迟到、不早退、不中途离校'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'b7967169-3811-460f-a20a-e0a7acfe361c'}, page_content='。工作时间：星期一至星期四7:55-16:55 星期五7:55-16:152、所有教职工实行考勤打卡制度，工作日内'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'b7967169-3811-460f-a20a-e0a7acfe361c'}, page_content='，工作日内，每天需打卡两次，上午上班一次和下午下班一次'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'b7967169-3811-460f-a20a-e0a7acfe361c'}, page_content='。3、教职员工因故(特殊情况除外)晚到或早退，应事先履行请假手续，经批准后方可离校'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '75242beb-716b-4db8-954c-21d23018ee84'}, page_content='。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'c8ce317c-ce39-40c3-87e7-d4137a021c91'}, page_content='。请假，需事先在钉钉系统中提交申请'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'c8ce317c-ce39-40c3-87e7-d4137a021c91'}, page_content='。有效的请假流程为：（1）员工休假必须事先向部门负责人申请'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'c8ce317c-ce39-40c3-87e7-d4137a021c91'}, page_content='，将工作交接清楚方可休假；（2）2 天以内的假期必须经过部门分管领导审批；（3）3 天以上的假期必须经过校长审批'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '420cbb31-dd82-4503-af33-ef46d597c715'}, page_content='。如遇紧急情况，口头申请请假的，应在上班后两天内办理补请假手续，未在规定时间内办理的，逾期无效，按旷工处理'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '420cbb31-dd82-4503-af33-ef46d597c715'}, page_content='。4、无工作理由，超过上班时间到岗的，视为迟到；未到下班时间提前离校的，视为早退；中途未经批准离校'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '420cbb31-dd82-4503-af33-ef46d597c715'}, page_content='，视为早退；中途未经批准离校，视为旷工；迟到、早退、旷工者按照相关办法处理'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '72fd1241-f878-4e06-9e93-0c1d3828a0ca'}, page_content='。5、考勤员徇私舞弊、弄虚作假的，按学校奖惩规定处理。情节严重的，予以通报批评直至解聘。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'doc_id': '745cc76e-8075-4cac-8895-4cbbbedabefa'}, page_content='第三节休假规定\\n休假分以下八种：事假、病假、婚假、丧假、产假、哺乳假、工伤假、调休。1、事假：（1）请假必须严格按照学校规定的请假程序，应由本人以书面形式，应在前两日办理手续，特殊情况应通过电话或者口头请假，应在事假结束于2 个工作日内完成补办请假手续。未经请假或请假未准而擅自离岗者，以旷工论处。（2）事假最小计算单位为半天，事假一次不得超过3 天。（3）事假：基本工资和岗位津贴均按请假天数占实际上班天数比例来算。（4）请假理由不充分或致工作妨碍时，可酌情缩短假期、或延期给假、或不予给假。（5）请假者必须将所任课务或经办事务交待给代理人员，并于请假单内注明。\\n2、病假：因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。（1）教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，应在病假结束于2 个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。(2)病假按照工龄系数，对病假日工资进行扣除。\\n<table><caption>病假发放标准：</caption>\\n<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\\n<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\\n<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\\n<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\\n<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\\n<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\\n<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\\n<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\\n<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\\n</table>\\n3、婚假：全体教职工达到国家法律（男方22 周岁，女方20 周岁）规定的，经过法定程序办理结婚手续的，可凭结婚证申请婚假15 天（均含休息日）。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'ba3c9793-c976-4ad4-bf4c-736355fffecc'}, page_content='（1）婚假期间员工工资照发。\\n（2）为了保证教学活动的顺利进行，提倡婚假安排在寒暑假。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'ba3c9793-c976-4ad4-bf4c-736355fffecc'}, page_content='4、丧假：员工因配偶或直系亲属丧亡时'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'ba3c9793-c976-4ad4-bf4c-736355fffecc'}, page_content='，可申请丧假：配偶、父母（公婆、岳父母）、子女及其配偶、祖父母、外祖父母、孙子女（外孙子女）及其配偶、曾祖父母、曾外祖父母丧亡'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'ba3c9793-c976-4ad4-bf4c-736355fffecc'}, page_content='，丧假3 天'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'ba3c9793-c976-4ad4-bf4c-736355fffecc'}, page_content='。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'ba3c9793-c976-4ad4-bf4c-736355fffecc'}, page_content='5、产假：符合计划生育政策规定的女性员工可享受产假'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'cdb61c93-b1cb-4f57-b3db-25dc45469971'}, page_content='（1）女教职员工的法定产假为158 天，其中产前可休假15 天；\\n（2）怀孕不满四个月流产的，可给予l5-30 天的产假；'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'cdb61c93-b1cb-4f57-b3db-25dc45469971'}, page_content='（3）怀孕满四个月以上流产的，可给予40 天的产假；\\n（4）男教职员工在配偶分娩时可休15 天陪护假；'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '3bf91ce2-1326-4e31-abb2-8f0f66f2ab28'}, page_content='（4）男教职员工在配偶分娩时可休15 天陪护假；'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '3bf91ce2-1326-4e31-abb2-8f0f66f2ab28'}, page_content='（5）女职工产前检查，可按照医院的日期，调整好课务之后去检查。每次产检准假半天，并提供产检相关凭证；'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '3bf91ce2-1326-4e31-abb2-8f0f66f2ab28'}, page_content='（6）以上产假天数为日历天数，包含法定节假日和休息日。\\n（7）产假期间薪资'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '5efdd28b-caa3-4626-9428-e0446c4a36cb'}, page_content='（7）产假期间薪资'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '5efdd28b-caa3-4626-9428-e0446c4a36cb'}, page_content='根据《福建新计生条例第四十一条规定》：妇女怀孕、生育和哺乳期间，按照国家和本省有关规定享受特殊劳动保护并可以获得帮助和补偿'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '5efdd28b-caa3-4626-9428-e0446c4a36cb'}, page_content='。产假期间工资照发，不影响晋升。①保胎假，工资按照病假发'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '5efdd28b-caa3-4626-9428-e0446c4a36cb'}, page_content='保胎假需由医生开证明，所以按病假待遇发放工资。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '2daa4c8f-b5eb-422d-bc35-98113349dd0c'}, page_content='保胎假需由医生开证明，所以按病假待遇发放工资。\\n②产前假，工资按照病假计算。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '2daa4c8f-b5eb-422d-bc35-98113349dd0c'}, page_content='②产前假，工资按照病假计算。\\n③产假工资：产假期间领取生育津贴，生育津贴没有覆盖的产假工资按照基本工资标准发放。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '66a11683-e416-4ae3-81eb-7d16a72e5301'}, page_content='6、哺乳假：哺乳期行政部门、教辅岗位职工可在不影响工作的前提下，婴儿不满一周岁的，每天准假两个小时，上午一小时，下午一小时'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '66a11683-e416-4ae3-81eb-7d16a72e5301'}, page_content='，上午一小时，下午一小时，但须事先在人事部备案'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '66a11683-e416-4ae3-81eb-7d16a72e5301'}, page_content='。哺乳期教师岗位在保证教学工作正常开展、保证教学质量的前提下，可以不坐班。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '59a1e05d-e626-4697-ab8f-93a01c79d383'}, page_content='7、工伤假：员工在上下班途中遭遇机动车交通事故的（交管部门出具机动车事故报告），或工作时、因公外出执行工作任务期间'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '59a1e05d-e626-4697-ab8f-93a01c79d383'}, page_content='，遭受身体伤害需要医护治疗的，根据国家有关规定给予工伤假'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'd7dd3e40-e8e6-4e28-a174-f136db4f60c6'}, page_content='。8、调休：各职能部门因工作需要，需要在工作日、节假日安排本部门加班或值班的，应由行政部门书面报送至人力资源部'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'd7dd3e40-e8e6-4e28-a174-f136db4f60c6'}, page_content='，如遇突发情况可事后补办手续'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'd7dd3e40-e8e6-4e28-a174-f136db4f60c6'}, page_content='。审批通过后，加班或值班时间可申请调休，教职工本人需填写《员工请假申请单》，报相关部门人员签字，并交给人事部核算考勤'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '94fe85d2-9cc9-405b-a2c3-8eb639a9cc27'}, page_content='。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'ed0746fd-10e7-4eb6-a300-c3e426c78c0d'}, page_content='9、以下情况视同出勤：持有学校书面通知，经部门负责人同意参加家长会的'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'ed0746fd-10e7-4eb6-a300-c3e426c78c0d'}, page_content='。以上，依本规则所请各假如发现有虚假行为者，一经查明，除以旷工论处外，并根据学校奖惩规定予以处罚。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'e44400b5-bf53-4739-af89-f0edddd5dadf'}, page_content='第四节加班和调休规定'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '30222f4c-c32b-4b18-b90e-2c6727a9f05b'}, page_content='1、学校以下列日期为例行公休日(若有变更需事先公布)，但因学校工作需要可指定照常上班'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '30222f4c-c32b-4b18-b90e-2c6727a9f05b'}, page_content='，以加班计算：(1)法定节假日(2)周六、周日2、正常工作日，延长工作时间连续达到4 小时以上的方可计算加班'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '7a807ade-0453-4fe6-a415-9713950aef51'}, page_content='。（加班需提前申请），加班需有打卡记录，无打卡记录支撑的加班时间，不计加班。加班费按照实际加班时长的2倍计算'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '7a807ade-0453-4fe6-a415-9713950aef51'}, page_content='。3、加班以调休等额返还（代替），凡调休人员应填写《请假申请表》，选择“调休”一栏，经所在部门分管领导签字后，交由人事处核实备案'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '8bd274a4-969a-419a-8615-0c07469decab'}, page_content='。4、行政岗及教辅岗都需要参与法定节假日轮流值班。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '16f00d24-8ba3-4f9e-9828-31ecb4e5095f'}, page_content='第五节违规违纪处理'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '16f00d24-8ba3-4f9e-9828-31ecb4e5095f'}, page_content='1'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '16f00d24-8ba3-4f9e-9828-31ecb4e5095f'}, page_content='. 迟到、早退(1)劳动考勤是公司支付薪资的依据和职工年度岗位考核内容之一'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '16f00d24-8ba3-4f9e-9828-31ecb4e5095f'}, page_content='。（2）迟到或早退60分钟以上（含60 分钟），每次视同缺勤1 天'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '16f00d24-8ba3-4f9e-9828-31ecb4e5095f'}, page_content='。（3）职工迟到、早退、脱岗累计超过3 次的（含），从第1 次起，每次扣减工资50 元。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '0e704480-73ad-44b4-9483-604e51ac6db2'}, page_content='2. 缺打卡\\n员工上下班无打卡或者有效签注，又无有效证明的视为旷工或早退半天。\\n3. 旷工'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '0e704480-73ad-44b4-9483-604e51ac6db2'}, page_content='3. 旷工\\n员工有以下情形之一未能出勤的，视为旷工：\\n⑴未按规定程序办理请假手续的或虽请假但未经批准，离开工作岗位不上班的；'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '0e704480-73ad-44b4-9483-604e51ac6db2'}, page_content='⑵提供虚假的证明材料获得准假的；'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '413dcb65-07b8-4317-84d3-a500a6d6099b'}, page_content='⑵提供虚假的证明材料获得准假的；\\n⑶迟到、早退或擅离学校达1 小时以上的；'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '413dcb65-07b8-4317-84d3-a500a6d6099b'}, page_content='⑷谎报请假原因，骗取、伪造、涂改病例证明或领导签字的；\\n⑸事假未经批准的；'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '413dcb65-07b8-4317-84d3-a500a6d6099b'}, page_content='⑸事假未经批准的；\\n⑹假满未经续假或未被同意续假的，或无出差审批手续的；'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '4bcc33b7-e71f-4bc0-b054-214f7cde5081'}, page_content='⑹假满未经续假或未被同意续假的，或无出差审批手续的；\\n⑺不服从学校应工作需要进行的正常调动和分配，有岗不上的；'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '4bcc33b7-e71f-4bc0-b054-214f7cde5081'}, page_content='⑻以公出或病、事假为由，工作时间在外干私活的；⑼其它法律规定的情形。\\n4.违规处理'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'ec5e7da4-dc47-4e11-8662-f9b1c8c1b5d1'}, page_content='(1)无故缺勤、未经批准备案的假期均按照旷工处理；'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'b5fb3046-637b-4e43-9e81-880389b67894'}, page_content='(2)旷工以0.5 天为单位，按照缺勤时间的三倍扣发工资；(3)连续旷工超过3 天，或全年累计旷工超过7 天的，无条件辞退。5'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '5c5aeb97-53e0-4d93-8447-3b8d87a3431a'}, page_content='. 维护学校财产学校物品（包括发给员工使用的物品）均为学校财产，无论疏忽或有意损坏，当事人必须酌情赔偿'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '5c5aeb97-53e0-4d93-8447-3b8d87a3431a'}, page_content='。员工如凡有盗窃行为，学校将立即予解除劳动合同，并视情节轻重交由公安部门处理'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '5c5aeb97-53e0-4d93-8447-3b8d87a3431a'}, page_content='。企业形象是学校非常重要的财富，维护好企业形象是每个员工必须遵守的规则'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '06db4a36-e8dd-401c-9eef-67fee5a46fb0'}, page_content='。员工必须严格遵守学校的企业文化，经营理念和管理制度，充分维护和支持学校的企业形象建设'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '06db4a36-e8dd-401c-9eef-67fee5a46fb0'}, page_content='。任何人不得出现有损学校团队建设、诋毁学校企业管理和企业文化的语言行为'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '22156724-9af4-4d15-b24e-03bb9aab0b91'}, page_content='。若教职工出现有损学校形象和荣誉的情况，由校长与当事人面谈，根据情节严重程度给与警告、处分，如不改正者，学校给予解除劳动合同处理'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '22156724-9af4-4d15-b24e-03bb9aab0b91'}, page_content='，学校给予解除劳动合同处理，并保留法律追究的权利'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '22156724-9af4-4d15-b24e-03bb9aab0b91'}, page_content='。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'doc_id': '886678cf-4f45-4bf6-8cac-e7ae2f62659d'}, page_content='<table>\\n<tr><td  >级别</td><td  >火车 （含高铁、动车、全列软席列车）</td><td  >轮船 （不包括 旅游船）</td><td  >飞机</td><td  >其他交通工具 （不包括出租 小汽车）</td></tr>\\n<tr><td  >享受副部级 待遇及以上 人员</td><td  >火车软席（软座、软卧），高铁/动车商 务座，全列软席列车一等软座</td><td  >一等舱</td><td  >头等舱</td><td  >凭据报销</td></tr>\\n<tr><td  >秘书长及副 秘书长</td><td  >火车软席（软座、软卧），高铁/动车一 等座，全列软席列车一等软座</td><td  >二等舱</td><td  >经济舱</td><td  >凭据报销</td></tr>\\n<tr><td  >其余人员</td><td  >火车硬席（硬座、硬卧），高铁/动车二 等座、全列软席列车二等软座</td><td  >三等舱</td><td  >经济舱</td><td  >凭据报销</td></tr>\\n</table>'),\n",
       " Document(metadata={'type': 'sm_chunk', 'doc_id': '87ec1b4d-d405-4aa3-8de8-1f83c1583a31'}, page_content='<table><caption>伙食补助费参考以下标准：</caption>\\n<tr><td  >地区</td><td  >伙食补助费标准</td></tr>\\n<tr><td  >西藏、青海、新疆</td><td  >120 元/人、天</td></tr>\\n<tr><td  >其他省份</td><td  >100 元/人、天</td></tr>\\n</table>'),\n",
       " Document(metadata={'type': 'sm_chunk', 'doc_id': 'afa8e13d-0d63-452e-a443-214c20ad6fd9'}, page_content='差旅费用标准\\n差旅费开支范围包括工作人员临时到常驻地以外地区公务出差所发生的城市间交通费、住宿费、伙食补助费和市内交通费。一、城市间交通费城市间交通费是指工作人员因公到常驻地以外地区出差乘坐火车、轮船、飞机等交通工具所发生的费用。1.出差人员在不影响公务、确保安全的前提下，选乘经济便捷的交通工具。2.出差人员要按照规定等级乘坐交通工具，未按规定乘坐的，超支部分自理。乘坐交通工具的等级见下表：\\n<table>\\n<tr><td  >级别</td><td  >火车 （含高铁、动车、全列软席列车）</td><td  >轮船 （不包括 旅游船）</td><td  >飞机</td><td  >其他交通工具 （不包括出租 小汽车）</td></tr>\\n<tr><td  >享受副部级 待遇及以上 人员</td><td  >火车软席（软座、软卧），高铁/动车商 务座，全列软席列车一等软座</td><td  >一等舱</td><td  >头等舱</td><td  >凭据报销</td></tr>\\n<tr><td  >秘书长及副 秘书长</td><td  >火车软席（软座、软卧），高铁/动车一 等座，全列软席列车一等软座</td><td  >二等舱</td><td  >经济舱</td><td  >凭据报销</td></tr>\\n<tr><td  >其余人员</td><td  >火车硬席（硬座、硬卧），高铁/动车二 等座、全列软席列车二等软座</td><td  >三等舱</td><td  >经济舱</td><td  >凭据报销</td></tr>\\n</table>\\n备注：\\n享受副部级待遇及以上人员出差，因工作需要，随行一人可乘坐同等级交通工具；乘坐飞机的，民航发展基金、燃油附加费可以凭据报销；乘坐飞机、火车、轮船等交通工具的，每人次可以购买交通意外保险一份。由我会统一购买交通意外保险的，不再重复购买。3.我会工作人员出差，高铁最短5 个小时内能够到达目的地的，原则上应乘坐高铁，如遇特殊情况，经分管副秘书长、秘书长审批后，可乘坐飞机。4.国内出差购买机票,应当按照厉行节约和支持本国航空公司发展的原则,优先购买通过政府采购方式确定的我国航空公司航班优惠机票。飞机票应通过定点供应商采购。二、住宿费住宿费是指工作人员因公出差期间入住宾馆（包括饭店、招待所，下同）发生的房租费用。享受副部级待遇及以上人员住普通套间，秘书长及以下人员住单间或标准间。出差人员应当在职务级别对应的住宿费标准限额内，选择安全、经济、便捷的宾馆住宿。国内出差发生的住宿，原则上应当按照住宿费标准执行，如遇特殊情况（如对方组织单位指定或推荐酒店等情况），超出费用标准的，须事先报分管资金的副秘书长、秘书长批准后方可报销。住宿费按照财政部《中央和国家机关工作人员赴地方差旅住宿费标准明细表》（财行[2016]71号）执行。三、伙食补助费伙食补助费是指对工作人员在因公出差期间给予的伙食补助费用。伙食补助费按出差自然(日历)天数计算，按规定标准包干使用。出差人员应当自行用餐。凡由接待单位统一安排用餐的，不再发放伙食补助费。\\t'),\n",
       " Document(metadata={'type': 'sm_chunk', 'doc_id': '85a16fb6-d0b7-4792-ad85-518ea21b8cd5'}, page_content='2\\n<table><caption>伙食补助费参考以下标准：</caption>\\n<tr><td  >地区</td><td  >伙食补助费标准</td></tr>\\n<tr><td  >西藏、青海、新疆</td><td  >120 元/人、天</td></tr>\\n<tr><td  >其他省份</td><td  >100 元/人、天</td></tr>\\n</table>'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'a19a61c6-f004-4cae-9ac1-3de3f861548e'}, page_content='四、市内交通费'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'a19a61c6-f004-4cae-9ac1-3de3f861548e'}, page_content='市内交通费是指工作人员因公出差期间发生的市内交通费用'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'a19a61c6-f004-4cae-9ac1-3de3f861548e'}, page_content='。出差人员的市内交通费按出差的自然（日历）天数计算，每人每天80 元包干使用'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': 'a19a61c6-f004-4cae-9ac1-3de3f861548e'}, page_content='。由接待单位或其他单位提供交通工具的，不再发放市内交通费。'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|序号|地区(城市)|地区(城市)|部级|司局级|其他人员|旺季地区|旺季期间|部级|司局级|其他人员|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='\\n|-------:|:-------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------|-------:|---------:|-----------:|:-------------------------------------------------|:--------------|:-------|:---------|:-----------|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|1|北京|全市|1100|650|500||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|2|天津|6个中心城区、滨海新区、东丽区、西青区、津南区、北辰区、武清区、宝坻区、静海区'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='、武清区、宝坻区、静海区、蓟县|800|480|380||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|2|天津|宁河区|600|350|320||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|3|河北|石家庄市、张家口市、秦皇岛市、廊坊市、承德市、保定市|800|450|350|张家口市|7-9月'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='、11-3月|1200|675|525|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|3|河北|石家庄市、张家口市、秦皇岛市、廊坊市、承德市'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='、秦皇岛市、廊坊市、承德市、保定市|800|450|350|秦皇岛市|7-8月|1200|680|500|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|3|河北|石家庄市、张家口市、秦皇岛市、廊坊市、承德市'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='、秦皇岛市、廊坊市、承德市、保定市|800|450|350|承德市|7-9月|1000|580|580|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|3|河北|其他地区|800|450|310||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|4|山西|太原市、大同市、晋城市|800|480|350||||||\\n|4|山西|临汾市|800|480|330||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|4|山西|阳泉市、长治市、晋中市|800|480|310||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|4|山西|其他地区|800|400|240||||||\\n|5|内蒙古|呼和浩特市|800|460|350||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|5|内蒙古|其他地区|800|460|320|海拉尔市、满洲里市、阿尔山市|7-9月|1200|690|480|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|5|内蒙古|其他地区|800|460|320|二连浩特市|7-9月|1000|580|400|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|5|内蒙古|其他地区|800|460|320|额济纳旗|9-10月|1200|690|480|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|6|辽宁|沈阳市|800|480|350||||||\\n|6|辽宁|其他地区|800|480|330||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|7|大连|全市|800|490|350|全市|7-9月|960|590|420|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|8|吉林|长春市、吉林市、延边州、长白山管理区|800|450|350|吉林市、延边州'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='、延边州、长白山管理区|7-9月|960|540|420|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|8|吉林|其他地区|750|400|300||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|9|黑龙江|哈尔滨市|800|450|350|哈尔滨市|7-9月|960|540|420|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|9|黑龙江|其他地区|750|450|300|牡丹江市、伊春市、大兴安岭地区、黑河市'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='、伊春市、大兴安岭地区、黑河市、佳木斯市|6-8月|900|540|360|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|10|上海|全市|1100|600|500||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|11|江苏|南京市、苏州市、无锡市、常州市、镇江市|900|490|380||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|11|江苏|其他地区|900|490|360||||||\\n|12|浙江|杭州市|900|500|400||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|12|浙江|其他地区|800|490|340||||||\\n|13|宁波|全市|800|450|350||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|14|安徽|全省|800|460|350||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|15|福建|福州市、泉州市、平潭综合实验区|900|480|380||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|15|福建|其他地区|900|480|350||||||\\n|16|厦门|全市|900|500|400||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|17|江西|全省|800|470|350||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|18|山东|济南市、淄博市、枣庄市、东营市、烟台市、潍坊市、济宁市、泰安市、威海市、日照市|800|480|380|烟台市'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='、威海市、日照市|7-9月|960|570|450|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|18|山东|其他地区|800|460|360||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|19|青岛|全市|800|490|380|全市|7-9月|960|590|450|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|20|河南|郑州市|900|480|380||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|20|河南|其他地区|800|480|330|洛阳市|4-5月上旬|1200|720|500|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|21|湖北|武汉市|800|480|350||||||\\n|21|湖北|其他地区|800|480|320||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|22|湖南|长沙市|800|450|350||||||\\n|22|湖南|其他地区|800|450|330||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|23|广东|广州市、珠海市、佛山市、东莞市、中山市、江门市|900|550|450||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|23|广东|其他地区|850|530|420||||||\\n|24|深圳|全市|900|550|450||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|25|广西|南宁市|800|470|350||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|25|广西|其他地区|800|470|330|桂林市、北海市|1-2月、7-9月|1040|610|430|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|26|海南|海口市、三沙市、儋州市、五指山市、文昌市、琼海市、万宁市、东方市、定安县、屯昌县、澄迈县、临高县、白沙县、昌江县'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='、临高县、白沙县、昌江县、乐东县、陵水县、保亭县、琼中县、洋浦开发区|800|500|350|海口市、文昌市'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='、文昌市、澄迈县|11-2月|1040|650|450|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|26|海南|海口市、三沙市、儋州市、五指山市、文昌市、琼海市、万宁市、东方市、定安县、屯昌县、澄迈县、临高县、白沙县、昌江县'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='、临高县、白沙县、昌江县、乐东县、陵水县、保亭县、琼中县、洋浦开发区|800|500|350|琼海市、万宁市、陵水县'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='、万宁市、陵水县、保亭县|11-3月|1040|650|450|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|26|海南|三亚市|1000|600|400|三亚市|10-4月|1200|720|480|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|27|重庆|9个中心城区、北部新区|800|480|370||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|27|重庆|其他地区|770|450|300||||||\\n|28|四川|成都市|900|470|370||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|28|四川|阿坝州、甘孜州|800|430|330||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|28|四川|绵阳市、乐山市、雅安市|800|430|320||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|28|四川|宜宾市|800|430|300||||||\\n|28|四川|凉山州|750|430|330||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|28|四川|德阳市、遂宁市、巴中市|750|430|310||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|28|四川|其他地区|750|430|300||||||\\n|29|贵州|贵阳市|800|470|370||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|29|贵州|其他地区|750|450|300||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|30|云南|昆明市、大理州、丽江市、迪庆州、西双版纳州|900|480|380||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|30|云南|其他地区|900|480|330||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|31|西藏|拉萨市|800|500|350|拉萨市|6-9月|1200|750|530|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|31|西藏|其他地区|500|400|300|其他地区|6-9月|800|500|350|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|32|陕西|西安市|800|460|350||||||\\n|32|陕西|榆林市、延安市|680|350|300||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|32|陕西|杨凌区|680|320|260||||||\\n|32|陕西|咸阳市、宝鸡市|600|320|260||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|32|陕西|渭南市、韩城市|600|300|260||||||\\n|32|陕西|其他地区|600|300|230||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|33|甘肃|兰州市|800|470|350||||||\\n|33|甘肃|其他地区|700|450|310||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|34|青海|西宁市|800|500|350|西宁市|6-9月|1200|750|530|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|34|青海|玉树州、果洛州|600|350|300|玉树州|5-9月|900|525|450|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|34|青海|海北州、黄南州|600|350|250|海北州、黄南州|5-9月|900|525|375|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|34|青海|海东市、海南州|600|300|250|海东市、海南州|5-9月|900|450|375|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|34|青海|海西州|600|300|200|海西州|5-9月|900|450|300|'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|35|宁夏|银川市|800|470|350||||||\\n|35|宁夏|其他地区|800|430|330||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|36|新疆|乌鲁木齐市|800|480|350||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|36|新疆|石河子市、克拉玛依市、昌吉州、伊犁州、阿勒泰地区、博州、吐鲁番市、哈密地区、巴州'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='、吐鲁番市、哈密地区、巴州、和田地区|800|480|340||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|36|新疆|克州|800|480|320||||||\\n|36|新疆|喀什地区|780|480|300||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'is_table': 0, 'doc_id': '1fe784ae-b7cd-4b11-9388-4a554debc230'}, page_content='|36|新疆|阿克苏地区|700|450|300||||||\\n|36|新疆|塔城地区|700|400|300||||||'),\n",
       " Document(metadata={'type': 'sm_chunk', 'doc_id': '67191185-e808-4f34-8d7d-a9acc7356d77'}, page_content='### 以下是中央和国家机关工作人员赴地方差旅住宿费标准明细表： \\n\\n |序号|地区(城市)|地区(城市)|部级|司局级|其他人员|旺季地区|旺季期间|部级|司局级|其他人员|\\n|-------:|:-------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------|-------:|---------:|-----------:|:-------------------------------------------------|:--------------|:-------|:---------|:-----------|\\n|1|北京|全市|1100|650|500||||||\\n|2|天津|6个中心城区、滨海新区、东丽区、西青区、津南区、北辰区、武清区、宝坻区、静海区、蓟县|800|480|380||||||\\n|2|天津|宁河区|600|350|320||||||\\n|3|河北|石家庄市、张家口市、秦皇岛市、廊坊市、承德市、保定市|800|450|350|张家口市|7-9月、11-3月|1200|675|525|\\n|3|河北|石家庄市、张家口市、秦皇岛市、廊坊市、承德市、保定市|800|450|350|秦皇岛市|7-8月|1200|680|500|\\n|3|河北|石家庄市、张家口市、秦皇岛市、廊坊市、承德市、保定市|800|450|350|承德市|7-9月|1000|580|580|\\n|3|河北|其他地区|800|450|310||||||\\n|4|山西|太原市、大同市、晋城市|800|480|350||||||\\n|4|山西|临汾市|800|480|330||||||\\n|4|山西|阳泉市、长治市、晋中市|800|480|310||||||\\n|4|山西|其他地区|800|400|240||||||\\n|5|内蒙古|呼和浩特市|800|460|350||||||\\n|5|内蒙古|其他地区|800|460|320|海拉尔市、满洲里市、阿尔山市|7-9月|1200|690|480|\\n|5|内蒙古|其他地区|800|460|320|二连浩特市|7-9月|1000|580|400|\\n|5|内蒙古|其他地区|800|460|320|额济纳旗|9-10月|1200|690|480|\\n|6|辽宁|沈阳市|800|480|350||||||\\n|6|辽宁|其他地区|800|480|330||||||\\n|7|大连|全市|800|490|350|全市|7-9月|960|590|420|\\n|8|吉林|长春市、吉林市、延边州、长白山管理区|800|450|350|吉林市、延边州、长白山管理区|7-9月|960|540|420|\\n|8|吉林|其他地区|750|400|300||||||\\n|9|黑龙江|哈尔滨市|800|450|350|哈尔滨市|7-9月|960|540|420|\\n|9|黑龙江|其他地区|750|450|300|牡丹江市、伊春市、大兴安岭地区、黑河市、佳木斯市|6-8月|900|540|360|\\n|10|上海|全市|1100|600|500||||||\\n|11|江苏|南京市、苏州市、无锡市、常州市、镇江市|900|490|380||||||\\n|11|江苏|其他地区|900|490|360||||||\\n|12|浙江|杭州市|900|500|400||||||\\n|12|浙江|其他地区|800|490|340||||||\\n|13|宁波|全市|800|450|350||||||\\n|14|安徽|全省|800|460|350||||||\\n|15|福建|福州市、泉州市、平潭综合实验区|900|480|380||||||\\n|15|福建|其他地区|900|480|350||||||\\n|16|厦门|全市|900|500|400||||||\\n|17|江西|全省|800|470|350||||||\\n|18|山东|济南市、淄博市、枣庄市、东营市、烟台市、潍坊市、济宁市、泰安市、威海市、日照市|800|480|380|烟台市、威海市、日照市|7-9月|960|570|450|\\n|18|山东|其他地区|800|460|360||||||\\n|19|青岛|全市|800|490|380|全市|7-9月|960|590|450|\\n|20|河南|郑州市|900|480|380||||||\\n|20|河南|其他地区|800|480|330|洛阳市|4-5月上旬|1200|720|500|\\n|21|湖北|武汉市|800|480|350||||||\\n|21|湖北|其他地区|800|480|320||||||\\n|22|湖南|长沙市|800|450|350||||||\\n|22|湖南|其他地区|800|450|330||||||\\n|23|广东|广州市、珠海市、佛山市、东莞市、中山市、江门市|900|550|450||||||\\n|23|广东|其他地区|850|530|420||||||\\n|24|深圳|全市|900|550|450||||||\\n|25|广西|南宁市|800|470|350||||||\\n|25|广西|其他地区|800|470|330|桂林市、北海市|1-2月、7-9月|1040|610|430|\\n|26|海南|海口市、三沙市、儋州市、五指山市、文昌市、琼海市、万宁市、东方市、定安县、屯昌县、澄迈县、临高县、白沙县、昌江县、乐东县、陵水县、保亭县、琼中县、洋浦开发区|800|500|350|海口市、文昌市、澄迈县|11-2月|1040|650|450|\\n|26|海南|海口市、三沙市、儋州市、五指山市、文昌市、琼海市、万宁市、东方市、定安县、屯昌县、澄迈县、临高县、白沙县、昌江县、乐东县、陵水县、保亭县、琼中县、洋浦开发区|800|500|350|琼海市、万宁市、陵水县、保亭县|11-3月|1040|650|450|\\n|26|海南|三亚市|1000|600|400|三亚市|10-4月|1200|720|480|\\n|27|重庆|9个中心城区、北部新区|800|480|370||||||\\n|27|重庆|其他地区|770|450|300||||||\\n|28|四川|成都市|900|470|370||||||\\n|28|四川|阿坝州、甘孜州|800|430|330||||||\\n|28|四川|绵阳市、乐山市、雅安市|800|430|320||||||\\n|28|四川|宜宾市|800|430|300||||||\\n|28|四川|凉山州|750|430|330||||||\\n|28|四川|德阳市、遂宁市、巴中市|750|430|310||||||\\n|28|四川|其他地区|750|430|300||||||\\n|29|贵州|贵阳市|800|470|370||||||\\n|29|贵州|其他地区|750|450|300||||||\\n|30|云南|昆明市、大理州、丽江市、迪庆州、西双版纳州|900|480|380||||||\\n|30|云南|其他地区|900|480|330||||||\\n|31|西藏|拉萨市|800|500|350|拉萨市|6-9月|1200|750|530|\\n|31|西藏|其他地区|500|400|300|其他地区|6-9月|800|500|350|\\n|32|陕西|西安市|800|460|350||||||\\n|32|陕西|榆林市、延安市|680|350|300||||||\\n|32|陕西|杨凌区|680|320|260||||||\\n|32|陕西|咸阳市、宝鸡市|600|320|260||||||\\n|32|陕西|渭南市、韩城市|600|300|260||||||\\n|32|陕西|其他地区|600|300|230||||||\\n|33|甘肃|兰州市|800|470|350||||||\\n|33|甘肃|其他地区|700|450|310||||||\\n|34|青海|西宁市|800|500|350|西宁市|6-9月|1200|750|530|\\n|34|青海|玉树州、果洛州|600|350|300|玉树州|5-9月|900|525|450|\\n|34|青海|海北州、黄南州|600|350|250|海北州、黄南州|5-9月|900|525|375|\\n|34|青海|海东市、海南州|600|300|250|海东市、海南州|5-9月|900|450|375|\\n|34|青海|海西州|600|300|200|海西州|5-9月|900|450|300|\\n|35|宁夏|银川市|800|470|350||||||\\n|35|宁夏|其他地区|800|430|330||||||\\n|36|新疆|乌鲁木齐市|800|480|350||||||\\n|36|新疆|石河子市、克拉玛依市、昌吉州、伊犁州、阿勒泰地区、博州、吐鲁番市、哈密地区、巴州、和田地区|800|480|340||||||\\n|36|新疆|克州|800|480|320||||||\\n|36|新疆|喀什地区|780|480|300||||||\\n|36|新疆|阿克苏地区|700|450|300||||||\\n|36|新疆|塔城地区|700|400|300||||||')]"
      ]
     },
     "execution_count": 109,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sub_docs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "id": "89b5a82a-f357-4b6e-94f7-9abf079adfdd",
   "metadata": {},
   "outputs": [],
   "source": [
    "sm_chunk_db = Chroma.from_documents(sub_docs,\n",
    "                                     embedding_model.get_embedding_fun(),\n",
    "                                     client=chroma_client,\n",
    "                                     collection_name=\"zhidu_db_sm_chunk\",\n",
    "                                     )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "id": "1d378b99-d9e7-4d23-a890-b05ff14cfafb",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.storage import InMemoryByteStore\n",
    "from langchain.retrievers.multi_vector import MultiVectorRetriever"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "id": "bb54ea88-be52-4df3-930e-f9954f26cf12",
   "metadata": {},
   "outputs": [],
   "source": [
    "store = InMemoryByteStore()\n",
    "id_key = \"doc_id\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 118,
   "id": "7cc56d56-d44e-4dc7-96a9-37302158250e",
   "metadata": {},
   "outputs": [],
   "source": [
    "retriever = MultiVectorRetriever(\n",
    "    vectorstore=sm_chunk_db,\n",
    "    byte_store=store,\n",
    "    id_key=id_key,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 119,
   "id": "20d5752f-96c2-4ba2-8adf-7ce2b2f1c386",
   "metadata": {},
   "outputs": [],
   "source": [
    "retriever.docstore.mset(list(zip(doc_ids, docs)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "id": "af8989ce-2237-4fb2-8760-5d3921b460f6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Document(metadata={'type': 'ori', 'is_table': 0}, page_content='四、市内交通费\\n市内交通费是指工作人员因公出差期间发生的市内交通费用。出差人员的市内交通费按出差的自然（日历）天数计算，每人每天80 元包干使用。由接待单位或其他单位提供交通工具的，不再发放市内交通费。'),\n",
       " Document(metadata={'type': 'ori', 'is_table': 1}, page_content='差旅费用标准\\n差旅费开支范围包括工作人员临时到常驻地以外地区公务出差所发生的城市间交通费、住宿费、伙食补助费和市内交通费。一、城市间交通费城市间交通费是指工作人员因公到常驻地以外地区出差乘坐火车、轮船、飞机等交通工具所发生的费用。1.出差人员在不影响公务、确保安全的前提下，选乘经济便捷的交通工具。2.出差人员要按照规定等级乘坐交通工具，未按规定乘坐的，超支部分自理。乘坐交通工具的等级见下表：\\n<table>\\n<tr><td  >级别</td><td  >火车 （含高铁、动车、全列软席列车）</td><td  >轮船 （不包括 旅游船）</td><td  >飞机</td><td  >其他交通工具 （不包括出租 小汽车）</td></tr>\\n<tr><td  >享受副部级 待遇及以上 人员</td><td  >火车软席（软座、软卧），高铁/动车商 务座，全列软席列车一等软座</td><td  >一等舱</td><td  >头等舱</td><td  >凭据报销</td></tr>\\n<tr><td  >秘书长及副 秘书长</td><td  >火车软席（软座、软卧），高铁/动车一 等座，全列软席列车一等软座</td><td  >二等舱</td><td  >经济舱</td><td  >凭据报销</td></tr>\\n<tr><td  >其余人员</td><td  >火车硬席（硬座、硬卧），高铁/动车二 等座、全列软席列车二等软座</td><td  >三等舱</td><td  >经济舱</td><td  >凭据报销</td></tr>\\n</table>\\n备注：\\n享受副部级待遇及以上人员出差，因工作需要，随行一人可乘坐同等级交通工具；乘坐飞机的，民航发展基金、燃油附加费可以凭据报销；乘坐飞机、火车、轮船等交通工具的，每人次可以购买交通意外保险一份。由我会统一购买交通意外保险的，不再重复购买。3.我会工作人员出差，高铁最短5 个小时内能够到达目的地的，原则上应乘坐高铁，如遇特殊情况，经分管副秘书长、秘书长审批后，可乘坐飞机。4.国内出差购买机票,应当按照厉行节约和支持本国航空公司发展的原则,优先购买通过政府采购方式确定的我国航空公司航班优惠机票。飞机票应通过定点供应商采购。二、住宿费住宿费是指工作人员因公出差期间入住宾馆（包括饭店、招待所，下同）发生的房租费用。享受副部级待遇及以上人员住普通套间，秘书长及以下人员住单间或标准间。出差人员应当在职务级别对应的住宿费标准限额内，选择安全、经济、便捷的宾馆住宿。国内出差发生的住宿，原则上应当按照住宿费标准执行，如遇特殊情况（如对方组织单位指定或推荐酒店等情况），超出费用标准的，须事先报分管资金的副秘书长、秘书长批准后方可报销。住宿费按照财政部《中央和国家机关工作人员赴地方差旅住宿费标准明细表》（财行[2016]71号）执行。三、伙食补助费伙食补助费是指对工作人员在因公出差期间给予的伙食补助费用。伙食补助费按出差自然(日历)天数计算，按规定标准包干使用。出差人员应当自行用餐。凡由接待单位统一安排用餐的，不再发放伙食补助费。\\t')]"
      ]
     },
     "execution_count": 120,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "query = \"出差交通费怎么算？\"\n",
    "retriever.invoke(query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "id": "39015c5c-b27d-479c-bfbc-691fd9b56700",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Document(metadata={'doc_id': 'a19a61c6-f004-4cae-9ac1-3de3f861548e', 'is_table': 0, 'type': 'sm_chunk'}, page_content='。出差人员的市内交通费按出差的自然（日历）天数计算，每人每天80 元包干使用'),\n",
       " Document(metadata={'doc_id': 'a19a61c6-f004-4cae-9ac1-3de3f861548e', 'is_table': 0, 'type': 'sm_chunk'}, page_content='市内交通费是指工作人员因公出差期间发生的市内交通费用')]"
      ]
     },
     "execution_count": 121,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sm_chunk_db.similarity_search(query, k=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9e49fc24-a822-4e4e-8e80-4865cbe731b9",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "21ff44b1-c076-44c9-a123-3d53f65d9ead",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0b3a3c83-adcd-43a5-88c9-d0ee991a4fa9",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "aa1fdc70-abe0-4d48-9cee-e137fc93f494",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9f5c7dee-615c-49fa-b2b5-413316fe8048",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "098eb6dd-6f7d-45dd-aa89-685a1481670a",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2731585a-cf85-4607-8646-c6c82a4429b9",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "139bc92c-4ede-4594-b6e3-a3f2b5618d5e",
   "metadata": {
    "tags": []
   },
   "source": [
    "## 多索引检索-总结检索"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "id": "40f00a72-9166-4ff3-bb93-0d236800224d",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.documents import Document\n",
    "from langchain_core.output_parsers import StrOutputParser\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from model import QwenLLM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "id": "b1ad0dc0-14da-4bf3-a2a7-c9f88a9a835f",
   "metadata": {},
   "outputs": [],
   "source": [
    "llm = QwenLLM()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "id": "0c6c954e-854b-4a74-8975-7d3674a94b13",
   "metadata": {},
   "outputs": [],
   "source": [
    "prompt_template = \"你是企业员工助手，熟悉公司考勤和报销标准等规章制度。请根据下面的文档:\\n\\n{doc}\\n 做一个简短的概括摘要改写，字数50字，并给出关键词\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "id": "31bf75a4-6cea-4569-8220-49df5016ccaf",
   "metadata": {},
   "outputs": [],
   "source": [
    "chain = (\n",
    "    {\"doc\": lambda x: x.page_content}\n",
    "    | ChatPromptTemplate.from_template(prompt_template)\n",
    "    | llm\n",
    "    | StrOutputParser()\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "id": "f4ae0009-2f67-49fe-b9bb-23b69287b512",
   "metadata": {},
   "outputs": [],
   "source": [
    "summaries = chain.batch(docs, {\"max_concurrency\": 1})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "id": "575385b1-05e2-4e2f-a5dc-3c106f3be42a",
   "metadata": {},
   "outputs": [],
   "source": [
    "summary_docs = []\n",
    "id_key = \"doc_id\"\n",
    "index_type = 'summary'\n",
    "for i, s in enumerate(summaries):\n",
    "    _id = doc_ids[i]\n",
    "    doc = docs[i]\n",
    "    if doc.metadata[\"is_table\"] == 1:\n",
    "        _doc = Document(page_content=doc.page_content,\n",
    "                        metadata={\"type\": index_type, id_key: _id})\n",
    "        summary_docs.extend([_doc])\n",
    "        continue\n",
    "        \n",
    "    _s = Document(page_content=s, \n",
    "                 metadata={\"type\": index_type, id_key: _id})\n",
    "    \n",
    "    summary_docs.extend([_s])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "id": "fcfcfbf4-1600-423f-85b8-7e98774453a4",
   "metadata": {},
   "outputs": [],
   "source": [
    "summary_chunk_db = Chroma.from_documents(summary_docs,\n",
    "                                     embedding_model.get_embedding_fun(),\n",
    "                                     client=chroma_client,\n",
    "                                     collection_name=\"zhidu_db_summary\",\n",
    "                                     )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "id": "cc281a36-a7da-4fda-afcb-2755f4feeb43",
   "metadata": {},
   "outputs": [],
   "source": [
    "store = InMemoryByteStore()\n",
    "id_key = \"doc_id\"\n",
    "\n",
    "# The retriever (empty to start)\n",
    "summary_retriever = MultiVectorRetriever(\n",
    "    vectorstore=summary_chunk_db,\n",
    "    byte_store=store,\n",
    "    id_key=id_key,\n",
    ")\n",
    "summary_retriever.docstore.mset(list(zip(doc_ids, docs)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "id": "5a6a818a-7994-4bd2-af26-48fb03ebd000",
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Document(metadata={'type': 'ori', 'is_table': 0}, page_content='四、市内交通费\\n市内交通费是指工作人员因公出差期间发生的市内交通费用。出差人员的市内交通费按出差的自然（日历）天数计算，每人每天80 元包干使用。由接待单位或其他单位提供交通工具的，不再发放市内交通费。'),\n",
       " Document(metadata={'type': 'ori', 'is_table': 1}, page_content='差旅费用标准\\n差旅费开支范围包括工作人员临时到常驻地以外地区公务出差所发生的城市间交通费、住宿费、伙食补助费和市内交通费。一、城市间交通费城市间交通费是指工作人员因公到常驻地以外地区出差乘坐火车、轮船、飞机等交通工具所发生的费用。1.出差人员在不影响公务、确保安全的前提下，选乘经济便捷的交通工具。2.出差人员要按照规定等级乘坐交通工具，未按规定乘坐的，超支部分自理。乘坐交通工具的等级见下表：\\n<table>\\n<tr><td  >级别</td><td  >火车 （含高铁、动车、全列软席列车）</td><td  >轮船 （不包括 旅游船）</td><td  >飞机</td><td  >其他交通工具 （不包括出租 小汽车）</td></tr>\\n<tr><td  >享受副部级 待遇及以上 人员</td><td  >火车软席（软座、软卧），高铁/动车商 务座，全列软席列车一等软座</td><td  >一等舱</td><td  >头等舱</td><td  >凭据报销</td></tr>\\n<tr><td  >秘书长及副 秘书长</td><td  >火车软席（软座、软卧），高铁/动车一 等座，全列软席列车一等软座</td><td  >二等舱</td><td  >经济舱</td><td  >凭据报销</td></tr>\\n<tr><td  >其余人员</td><td  >火车硬席（硬座、硬卧），高铁/动车二 等座、全列软席列车二等软座</td><td  >三等舱</td><td  >经济舱</td><td  >凭据报销</td></tr>\\n</table>\\n备注：\\n享受副部级待遇及以上人员出差，因工作需要，随行一人可乘坐同等级交通工具；乘坐飞机的，民航发展基金、燃油附加费可以凭据报销；乘坐飞机、火车、轮船等交通工具的，每人次可以购买交通意外保险一份。由我会统一购买交通意外保险的，不再重复购买。3.我会工作人员出差，高铁最短5 个小时内能够到达目的地的，原则上应乘坐高铁，如遇特殊情况，经分管副秘书长、秘书长审批后，可乘坐飞机。4.国内出差购买机票,应当按照厉行节约和支持本国航空公司发展的原则,优先购买通过政府采购方式确定的我国航空公司航班优惠机票。飞机票应通过定点供应商采购。二、住宿费住宿费是指工作人员因公出差期间入住宾馆（包括饭店、招待所，下同）发生的房租费用。享受副部级待遇及以上人员住普通套间，秘书长及以下人员住单间或标准间。出差人员应当在职务级别对应的住宿费标准限额内，选择安全、经济、便捷的宾馆住宿。国内出差发生的住宿，原则上应当按照住宿费标准执行，如遇特殊情况（如对方组织单位指定或推荐酒店等情况），超出费用标准的，须事先报分管资金的副秘书长、秘书长批准后方可报销。住宿费按照财政部《中央和国家机关工作人员赴地方差旅住宿费标准明细表》（财行[2016]71号）执行。三、伙食补助费伙食补助费是指对工作人员在因公出差期间给予的伙食补助费用。伙食补助费按出差自然(日历)天数计算，按规定标准包干使用。出差人员应当自行用餐。凡由接待单位统一安排用餐的，不再发放伙食补助费。\\t'),\n",
       " Document(metadata={'type': 'ori', 'is_table': 1}, page_content='### 以下是中央和国家机关工作人员赴地方差旅住宿费标准明细表： \\n\\n |序号|地区(城市)|地区(城市)|部级|司局级|其他人员|旺季地区|旺季期间|部级|司局级|其他人员|\\n|-------:|:-------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------|-------:|---------:|-----------:|:-------------------------------------------------|:--------------|:-------|:---------|:-----------|\\n|1|北京|全市|1100|650|500||||||\\n|2|天津|6个中心城区、滨海新区、东丽区、西青区、津南区、北辰区、武清区、宝坻区、静海区、蓟县|800|480|380||||||\\n|2|天津|宁河区|600|350|320||||||\\n|3|河北|石家庄市、张家口市、秦皇岛市、廊坊市、承德市、保定市|800|450|350|张家口市|7-9月、11-3月|1200|675|525|\\n|3|河北|石家庄市、张家口市、秦皇岛市、廊坊市、承德市、保定市|800|450|350|秦皇岛市|7-8月|1200|680|500|\\n|3|河北|石家庄市、张家口市、秦皇岛市、廊坊市、承德市、保定市|800|450|350|承德市|7-9月|1000|580|580|\\n|3|河北|其他地区|800|450|310||||||\\n|4|山西|太原市、大同市、晋城市|800|480|350||||||\\n|4|山西|临汾市|800|480|330||||||\\n|4|山西|阳泉市、长治市、晋中市|800|480|310||||||\\n|4|山西|其他地区|800|400|240||||||\\n|5|内蒙古|呼和浩特市|800|460|350||||||\\n|5|内蒙古|其他地区|800|460|320|海拉尔市、满洲里市、阿尔山市|7-9月|1200|690|480|\\n|5|内蒙古|其他地区|800|460|320|二连浩特市|7-9月|1000|580|400|\\n|5|内蒙古|其他地区|800|460|320|额济纳旗|9-10月|1200|690|480|\\n|6|辽宁|沈阳市|800|480|350||||||\\n|6|辽宁|其他地区|800|480|330||||||\\n|7|大连|全市|800|490|350|全市|7-9月|960|590|420|\\n|8|吉林|长春市、吉林市、延边州、长白山管理区|800|450|350|吉林市、延边州、长白山管理区|7-9月|960|540|420|\\n|8|吉林|其他地区|750|400|300||||||\\n|9|黑龙江|哈尔滨市|800|450|350|哈尔滨市|7-9月|960|540|420|\\n|9|黑龙江|其他地区|750|450|300|牡丹江市、伊春市、大兴安岭地区、黑河市、佳木斯市|6-8月|900|540|360|\\n|10|上海|全市|1100|600|500||||||\\n|11|江苏|南京市、苏州市、无锡市、常州市、镇江市|900|490|380||||||\\n|11|江苏|其他地区|900|490|360||||||\\n|12|浙江|杭州市|900|500|400||||||\\n|12|浙江|其他地区|800|490|340||||||\\n|13|宁波|全市|800|450|350||||||\\n|14|安徽|全省|800|460|350||||||\\n|15|福建|福州市、泉州市、平潭综合实验区|900|480|380||||||\\n|15|福建|其他地区|900|480|350||||||\\n|16|厦门|全市|900|500|400||||||\\n|17|江西|全省|800|470|350||||||\\n|18|山东|济南市、淄博市、枣庄市、东营市、烟台市、潍坊市、济宁市、泰安市、威海市、日照市|800|480|380|烟台市、威海市、日照市|7-9月|960|570|450|\\n|18|山东|其他地区|800|460|360||||||\\n|19|青岛|全市|800|490|380|全市|7-9月|960|590|450|\\n|20|河南|郑州市|900|480|380||||||\\n|20|河南|其他地区|800|480|330|洛阳市|4-5月上旬|1200|720|500|\\n|21|湖北|武汉市|800|480|350||||||\\n|21|湖北|其他地区|800|480|320||||||\\n|22|湖南|长沙市|800|450|350||||||\\n|22|湖南|其他地区|800|450|330||||||\\n|23|广东|广州市、珠海市、佛山市、东莞市、中山市、江门市|900|550|450||||||\\n|23|广东|其他地区|850|530|420||||||\\n|24|深圳|全市|900|550|450||||||\\n|25|广西|南宁市|800|470|350||||||\\n|25|广西|其他地区|800|470|330|桂林市、北海市|1-2月、7-9月|1040|610|430|\\n|26|海南|海口市、三沙市、儋州市、五指山市、文昌市、琼海市、万宁市、东方市、定安县、屯昌县、澄迈县、临高县、白沙县、昌江县、乐东县、陵水县、保亭县、琼中县、洋浦开发区|800|500|350|海口市、文昌市、澄迈县|11-2月|1040|650|450|\\n|26|海南|海口市、三沙市、儋州市、五指山市、文昌市、琼海市、万宁市、东方市、定安县、屯昌县、澄迈县、临高县、白沙县、昌江县、乐东县、陵水县、保亭县、琼中县、洋浦开发区|800|500|350|琼海市、万宁市、陵水县、保亭县|11-3月|1040|650|450|\\n|26|海南|三亚市|1000|600|400|三亚市|10-4月|1200|720|480|\\n|27|重庆|9个中心城区、北部新区|800|480|370||||||\\n|27|重庆|其他地区|770|450|300||||||\\n|28|四川|成都市|900|470|370||||||\\n|28|四川|阿坝州、甘孜州|800|430|330||||||\\n|28|四川|绵阳市、乐山市、雅安市|800|430|320||||||\\n|28|四川|宜宾市|800|430|300||||||\\n|28|四川|凉山州|750|430|330||||||\\n|28|四川|德阳市、遂宁市、巴中市|750|430|310||||||\\n|28|四川|其他地区|750|430|300||||||\\n|29|贵州|贵阳市|800|470|370||||||\\n|29|贵州|其他地区|750|450|300||||||\\n|30|云南|昆明市、大理州、丽江市、迪庆州、西双版纳州|900|480|380||||||\\n|30|云南|其他地区|900|480|330||||||\\n|31|西藏|拉萨市|800|500|350|拉萨市|6-9月|1200|750|530|\\n|31|西藏|其他地区|500|400|300|其他地区|6-9月|800|500|350|\\n|32|陕西|西安市|800|460|350||||||\\n|32|陕西|榆林市、延安市|680|350|300||||||\\n|32|陕西|杨凌区|680|320|260||||||\\n|32|陕西|咸阳市、宝鸡市|600|320|260||||||\\n|32|陕西|渭南市、韩城市|600|300|260||||||\\n|32|陕西|其他地区|600|300|230||||||\\n|33|甘肃|兰州市|800|470|350||||||\\n|33|甘肃|其他地区|700|450|310||||||\\n|34|青海|西宁市|800|500|350|西宁市|6-9月|1200|750|530|\\n|34|青海|玉树州、果洛州|600|350|300|玉树州|5-9月|900|525|450|\\n|34|青海|海北州、黄南州|600|350|250|海北州、黄南州|5-9月|900|525|375|\\n|34|青海|海东市、海南州|600|300|250|海东市、海南州|5-9月|900|450|375|\\n|34|青海|海西州|600|300|200|海西州|5-9月|900|450|300|\\n|35|宁夏|银川市|800|470|350||||||\\n|35|宁夏|其他地区|800|430|330||||||\\n|36|新疆|乌鲁木齐市|800|480|350||||||\\n|36|新疆|石河子市、克拉玛依市、昌吉州、伊犁州、阿勒泰地区、博州、吐鲁番市、哈密地区、巴州、和田地区|800|480|340||||||\\n|36|新疆|克州|800|480|320||||||\\n|36|新疆|喀什地区|780|480|300||||||\\n|36|新疆|阿克苏地区|700|450|300||||||\\n|36|新疆|塔城地区|700|400|300||||||'),\n",
       " Document(metadata={'type': 'ori', 'is_table': 1}, page_content='2\\n<table><caption>伙食补助费参考以下标准：</caption>\\n<tr><td  >地区</td><td  >伙食补助费标准</td></tr>\\n<tr><td  >西藏、青海、新疆</td><td  >120 元/人、天</td></tr>\\n<tr><td  >其他省份</td><td  >100 元/人、天</td></tr>\\n</table>')]"
      ]
     },
     "execution_count": 136,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "query = \"出差交通费怎么算？\"\n",
    "summary_retriever.invoke(query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "id": "80643116-fa45-4884-af1e-6e94a090129d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Document(metadata={'doc_id': 'a19a61c6-f004-4cae-9ac1-3de3f861548e', 'type': 'summary'}, page_content='摘要：市内交通费为出差期间每日80元定额，按自然天数计算，若使用接待单位车辆则不发放。\\n\\n关键词：市内交通费、出差、每人每天80元、自然（日历）天数、接待单位交通工具。'),\n",
       " Document(metadata={'doc_id': 'afa8e13d-0d63-452e-a443-214c20ad6fd9', 'type': 'summary'}, page_content='差旅费用标准\\n差旅费开支范围包括工作人员临时到常驻地以外地区公务出差所发生的城市间交通费、住宿费、伙食补助费和市内交通费。一、城市间交通费城市间交通费是指工作人员因公到常驻地以外地区出差乘坐火车、轮船、飞机等交通工具所发生的费用。1.出差人员在不影响公务、确保安全的前提下，选乘经济便捷的交通工具。2.出差人员要按照规定等级乘坐交通工具，未按规定乘坐的，超支部分自理。乘坐交通工具的等级见下表：\\n<table>\\n<tr><td  >级别</td><td  >火车 （含高铁、动车、全列软席列车）</td><td  >轮船 （不包括 旅游船）</td><td  >飞机</td><td  >其他交通工具 （不包括出租 小汽车）</td></tr>\\n<tr><td  >享受副部级 待遇及以上 人员</td><td  >火车软席（软座、软卧），高铁/动车商 务座，全列软席列车一等软座</td><td  >一等舱</td><td  >头等舱</td><td  >凭据报销</td></tr>\\n<tr><td  >秘书长及副 秘书长</td><td  >火车软席（软座、软卧），高铁/动车一 等座，全列软席列车一等软座</td><td  >二等舱</td><td  >经济舱</td><td  >凭据报销</td></tr>\\n<tr><td  >其余人员</td><td  >火车硬席（硬座、硬卧），高铁/动车二 等座、全列软席列车二等软座</td><td  >三等舱</td><td  >经济舱</td><td  >凭据报销</td></tr>\\n</table>\\n备注：\\n享受副部级待遇及以上人员出差，因工作需要，随行一人可乘坐同等级交通工具；乘坐飞机的，民航发展基金、燃油附加费可以凭据报销；乘坐飞机、火车、轮船等交通工具的，每人次可以购买交通意外保险一份。由我会统一购买交通意外保险的，不再重复购买。3.我会工作人员出差，高铁最短5 个小时内能够到达目的地的，原则上应乘坐高铁，如遇特殊情况，经分管副秘书长、秘书长审批后，可乘坐飞机。4.国内出差购买机票,应当按照厉行节约和支持本国航空公司发展的原则,优先购买通过政府采购方式确定的我国航空公司航班优惠机票。飞机票应通过定点供应商采购。二、住宿费住宿费是指工作人员因公出差期间入住宾馆（包括饭店、招待所，下同）发生的房租费用。享受副部级待遇及以上人员住普通套间，秘书长及以下人员住单间或标准间。出差人员应当在职务级别对应的住宿费标准限额内，选择安全、经济、便捷的宾馆住宿。国内出差发生的住宿，原则上应当按照住宿费标准执行，如遇特殊情况（如对方组织单位指定或推荐酒店等情况），超出费用标准的，须事先报分管资金的副秘书长、秘书长批准后方可报销。住宿费按照财政部《中央和国家机关工作人员赴地方差旅住宿费标准明细表》（财行[2016]71号）执行。三、伙食补助费伙食补助费是指对工作人员在因公出差期间给予的伙食补助费用。伙食补助费按出差自然(日历)天数计算，按规定标准包干使用。出差人员应当自行用餐。凡由接待单位统一安排用餐的，不再发放伙食补助费。\\t')]"
      ]
     },
     "execution_count": 137,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "summary_chunk_db.similarity_search(query, k=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "23e6f834-d863-4f10-a774-0ad6d101b9b1",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "737e27f1-0c6f-465d-a235-6c5632ffdbeb",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cc5685cf-aaf3-460d-b7aa-d48b0e6e6a75",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "467808c2-b49c-4302-8753-660e497a2fb8",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d45acbef-9ee7-4b81-9157-efb33c9e2fe3",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "290c6a53-c978-47fd-a5c0-e3413f22e02e",
   "metadata": {
    "tags": []
   },
   "source": [
    "## 多索引检索-假设问题检索"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "id": "47df61c5-de9c-4fa2-b6b6-fd6acdadba41",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_core.pydantic_v1 import BaseModel, Field\n",
    "from langchain_core.output_parsers import PydanticOutputParser\n",
    "from langchain_core.prompts import PromptTemplate\n",
    "from langchain_core.pydantic_v1 import BaseModel, Field, validator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "id": "c99cfb12-e778-401c-b4b0-2ba5d94d3953",
   "metadata": {},
   "outputs": [],
   "source": [
    "chain = (\n",
    "    {\"doc\": lambda x: x.page_content}\n",
    "    | ChatPromptTemplate.from_template(\n",
    "        \"你是企业员工助手，熟悉公司考勤和报销标准等规章制度。你的任务是提出在下面文档的内容中可以找到答案的3个假设性问题。:\\n\\n{doc}, 要求输出为中文，不包含解释性内容，格式列表格式如['问题1'， '问题2', '问题3'] \"\n",
    "    )\n",
    "    | llm\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "id": "afc27f17-7160-4778-bb6b-aba034e15ad7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Document(metadata={'type': 'ori', 'is_table': 0}, page_content='。工作时间：星期一至星期四7:55-16:55 星期五7:55-16:152、所有教职工实行考勤打卡制度，工作日内，每天需打卡两次，上午上班一次和下午下班一次。3、教职员工因故(特殊情况除外)晚到或早退，应事先履行请假手续，经批准后方可离校')"
      ]
     },
     "execution_count": 143,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "docs[4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 142,
   "id": "df13212d-e19f-4aef-9a37-8f9b605e5b23",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"['教职工在星期一至星期四的工作时间是多久？', '教职员工每天需要打卡几次？', '如果教职员工因故晚到或早退，需要履行什么手续？']\""
      ]
     },
     "execution_count": 142,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.invoke(docs[4])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "id": "c59d4b59-98c3-455d-b037-d05319a82df3",
   "metadata": {},
   "outputs": [],
   "source": [
    "class HypotheticalQuestions(BaseModel):\n",
    "    \"\"\"Generate hypothetical questions.\"\"\"\n",
    "\n",
    "    questions: List[str] = Field(..., description=\"List of questions\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 145,
   "id": "3fc71f5b-2e75-4967-b145-7478e28014bb",
   "metadata": {},
   "outputs": [],
   "source": [
    "question_docs = []\n",
    "id_key = \"doc_id\"\n",
    "index_type = 'hq'\n",
    "for i, doc in enumerate(docs):\n",
    "    _id = doc_ids[i]\n",
    "    for _ in range(3):\n",
    "        try:\n",
    "            hq = chain.invoke(doc)\n",
    "            res = eval(hq)\n",
    "            q = HypotheticalQuestions(questions=res)\n",
    "            \n",
    "            for i, question in enumerate(q.questions):\n",
    "                question_docs.extend(\n",
    "                    [Document(page_content=question, metadata={\"type\": index_type, id_key: _id})])\n",
    "            break\n",
    "        except:\n",
    "            continue"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "id": "f7cc3883-d2a6-464c-8f86-00d8d525d0a6",
   "metadata": {},
   "outputs": [],
   "source": [
    "hq_chunk_db = Chroma.from_documents(question_docs,\n",
    "                                     embedding_model.get_embedding_fun(),\n",
    "                                     client=chroma_client,\n",
    "                                     collection_name=\"zhidu_db_hq\",\n",
    "                                     )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "id": "74009a2e-8979-44a9-a2a7-4777e5a0dfca",
   "metadata": {},
   "outputs": [],
   "source": [
    "store = InMemoryByteStore()\n",
    "id_key = \"doc_id\"\n",
    "\n",
    "# The retriever (empty to start)\n",
    "hq_retriever = MultiVectorRetriever(\n",
    "    vectorstore=hq_chunk_db,\n",
    "    byte_store=store,\n",
    "    id_key=id_key,\n",
    ")\n",
    "hq_retriever.docstore.mset(list(zip(doc_ids, docs)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 149,
   "id": "18c0fa1c-fa9c-437b-8da2-f693dbb4d287",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Document(metadata={'type': 'ori', 'is_table': 0}, page_content='四、市内交通费\\n市内交通费是指工作人员因公出差期间发生的市内交通费用。出差人员的市内交通费按出差的自然（日历）天数计算，每人每天80 元包干使用。由接待单位或其他单位提供交通工具的，不再发放市内交通费。'),\n",
       " Document(metadata={'type': 'ori', 'is_table': 0}, page_content='。（加班需提前申请），加班需有打卡记录，无打卡记录支撑的加班时间，不计加班。加班费按照实际加班时长的2倍计算。3、加班以调休等额返还（代替），凡调休人员应填写《请假申请表》，选择“调休”一栏，经所在部门分管领导签字后，交由人事处核实备案')]"
      ]
     },
     "execution_count": 149,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "query = \"出差交通费怎么算？\"\n",
    "hq_retriever.invoke(query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "id": "dd477d71-7be3-488a-bb1f-ae19739cd115",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Document(metadata={'doc_id': 'a19a61c6-f004-4cae-9ac1-3de3f861548e', 'type': 'hq'}, page_content='市内交通费是按照什么方式计算的？'),\n",
       " Document(metadata={'doc_id': 'a19a61c6-f004-4cae-9ac1-3de3f861548e', 'type': 'hq'}, page_content='员工因公出差期间，每天的市内交通费用标准是多少？')]"
      ]
     },
     "execution_count": 150,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "query = \"出差交通费怎么算？\"\n",
    "hq_chunk_db.similarity_search(query, k=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ba9decae-bd6a-4391-8490-9b26082d1420",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "713d7edc-a145-449b-8bf0-2577afbab599",
   "metadata": {
    "tags": []
   },
   "source": [
    "## 融合检索"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4acf77f-3eb5-4daa-bc9b-a9ddc79f2462",
   "metadata": {},
   "source": [
    "- pip install rank_bm25\n",
    "- pip install jieba"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3a3714b4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 从向量数据库中获取所有文档\n",
    "import chromadb\n",
    "from chromadb.utils import embedding_functions\n",
    "from langchain_core.documents import Document\n",
    "chroma_client = chromadb.HttpClient(host=\"localhost\", port=8000)\n",
    "get_collection = chroma_client.get_collection(name='zhidu_db')\n",
    "all_data = get_collection.get(include=[\"documents\"])\n",
    "docs = []\n",
    "for doc in all_data['documents']:\n",
    "    docs.append(Document(page_content=doc))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 151,
   "id": "d7d3c47c-e4e2-401f-8451-f343007d43a3",
   "metadata": {},
   "outputs": [],
   "source": [
    "import jieba\n",
    "from langchain_community.retrievers import BM25Retriever\n",
    "from langchain.retrievers import EnsembleRetriever"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 152,
   "id": "f59d6425-8771-4b2c-99a0-5aed2da07d91",
   "metadata": {},
   "outputs": [],
   "source": [
    "def jieba_preprocessing_func(text: str):\n",
    "    return list(jieba.cut(text))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 153,
   "id": "8f099325-889f-4308-8696-6b399986a86c",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Building prefix dict from the default dictionary ...\n",
      "Loading model from cache /tmp/jieba.cache\n",
      "Loading model cost 0.851 seconds.\n",
      "Prefix dict has been built successfully.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "['我要', '请', '病假', '100', '天']"
      ]
     },
     "execution_count": 153,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "text = \"我要请病假100天\"\n",
    "jieba_preprocessing_func(text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 155,
   "id": "49a623a5-b46a-4ff5-b8c5-14468dc81e0f",
   "metadata": {},
   "outputs": [],
   "source": [
    "bm25_retriever = BM25Retriever.from_documents(docs, preprocess_func=jieba_preprocessing_func)\n",
    "bm25_retriever.k = 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 156,
   "id": "126cf3bb-0b00-4334-80ca-a69a168bdb2e",
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"我要请病假100天\"\n",
    "ret_docs = bm25_retriever.invoke(query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 157,
   "id": "751e9470-41d7-40dc-81cf-1e09b41178de",
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "####################################################################################################\n",
      "<table><caption>伙食补助费参考以下标准：</caption>\n",
      "<tr><td  >地区</td><td  >伙食补助费标准</td></tr>\n",
      "<tr><td  >西藏、青海、新疆</td><td  >120 元/人、天</td></tr>\n",
      "<tr><td  >其他省份</td><td  >100 元/人、天</td></tr>\n",
      "</table>\n",
      "####################################################################################################\n",
      "2\n",
      "<table><caption>伙食补助费参考以下标准：</caption>\n",
      "<tr><td  >地区</td><td  >伙食补助费标准</td></tr>\n",
      "<tr><td  >西藏、青海、新疆</td><td  >120 元/人、天</td></tr>\n",
      "<tr><td  >其他省份</td><td  >100 元/人、天</td></tr>\n",
      "</table>\n",
      "####################################################################################################\n",
      "第三节休假规定\n",
      "休假分以下八种：事假、病假、婚假、丧假、产假、哺乳假、工伤假、调休。1、事假：（1）请假必须严格按照学校规定的请假程序，应由本人以书面形式，应在前两日办理手续，特殊情况应通过电话或者口头请假，应在事假结束于2 个工作日内完成补办请假手续。未经请假或请假未准而擅自离岗者，以旷工论处。（2）事假最小计算单位为半天，事假一次不得超过3 天。（3）事假：基本工资和岗位津贴均按请假天数占实际上班天数比例来算。（4）请假理由不充分或致工作妨碍时，可酌情缩短假期、或延期给假、或不予给假。（5）请假者必须将所任课务或经办事务交待给代理人员，并于请假单内注明。\n",
      "2、病假：因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。（1）教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，应在病假结束于2 个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。(2)病假按照工龄系数，对病假日工资进行扣除。\n",
      "<table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table>\n",
      "3、婚假：全体教职工达到国家法律（男方22 周岁，女方20 周岁）规定的，经过法定程序办理结婚手续的，可凭结婚证申请婚假15 天（均含休息日）。\n"
     ]
    }
   ],
   "source": [
    "for doc in ret_docs:\n",
    "    print(\"#\"*100)\n",
    "    print(doc.page_content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 158,
   "id": "be438a9c-b195-4d1a-92da-2582f2bca7b7",
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"婚假如何请\"\n",
    "ret_docs = bm25_retriever.invoke(query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 159,
   "id": "8a49b799-b8b1-48cc-b88b-90ba2b1313c2",
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "####################################################################################################\n",
      "（1）婚假期间员工工资照发。\n",
      "（2）为了保证教学活动的顺利进行，提倡婚假安排在寒暑假。\n",
      "4、丧假：员工因配偶或直系亲属丧亡时，可申请丧假：配偶、父母（公婆、岳父母）、子女及其配偶、祖父母、外祖父母、孙子女（外孙子女）及其配偶、曾祖父母、曾外祖父母丧亡，丧假3 天。\n",
      "5、产假：符合计划生育政策规定的女性员工可享受产假\n",
      "####################################################################################################\n",
      "第三节休假规定\n",
      "休假分以下八种：事假、病假、婚假、丧假、产假、哺乳假、工伤假、调休。1、事假：（1）请假必须严格按照学校规定的请假程序，应由本人以书面形式，应在前两日办理手续，特殊情况应通过电话或者口头请假，应在事假结束于2 个工作日内完成补办请假手续。未经请假或请假未准而擅自离岗者，以旷工论处。（2）事假最小计算单位为半天，事假一次不得超过3 天。（3）事假：基本工资和岗位津贴均按请假天数占实际上班天数比例来算。（4）请假理由不充分或致工作妨碍时，可酌情缩短假期、或延期给假、或不予给假。（5）请假者必须将所任课务或经办事务交待给代理人员，并于请假单内注明。\n",
      "2、病假：因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。（1）教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，应在病假结束于2 个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。(2)病假按照工龄系数，对病假日工资进行扣除。\n",
      "<table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table>\n",
      "3、婚假：全体教职工达到国家法律（男方22 周岁，女方20 周岁）规定的，经过法定程序办理结婚手续的，可凭结婚证申请婚假15 天（均含休息日）。\n",
      "####################################################################################################\n",
      "|序号|地区(城市)|地区(城市)|部级|司局级|其他人员|旺季地区|旺季期间|部级|司局级|其他人员|\n",
      "|-------:|:-------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------|-------:|---------:|-----------:|:-------------------------------------------------|:--------------|:-------|:---------|:-----------|\n",
      "|1|北京|全市|1100|650|500||||||\n",
      "|2|天津|6个中心城区、滨海新区、东丽区、西青区、津南区、北辰区、武清区、宝坻区、静海区、蓟县|800|480|380||||||\n",
      "|2|天津|宁河区|600|350|320||||||\n",
      "|3|河北|石家庄市、张家口市、秦皇岛市、廊坊市、承德市、保定市|800|450|350|张家口市|7-9月、11-3月|1200|675|525|\n",
      "|3|河北|石家庄市、张家口市、秦皇岛市、廊坊市、承德市、保定市|800|450|350|秦皇岛市|7-8月|1200|680|500|\n",
      "|3|河北|石家庄市、张家口市、秦皇岛市、廊坊市、承德市、保定市|800|450|350|承德市|7-9月|1000|580|580|\n",
      "|3|河北|其他地区|800|450|310||||||\n",
      "|4|山西|太原市、大同市、晋城市|800|480|350||||||\n",
      "|4|山西|临汾市|800|480|330||||||\n",
      "|4|山西|阳泉市、长治市、晋中市|800|480|310||||||\n",
      "|4|山西|其他地区|800|400|240||||||\n",
      "|5|内蒙古|呼和浩特市|800|460|350||||||\n",
      "|5|内蒙古|其他地区|800|460|320|海拉尔市、满洲里市、阿尔山市|7-9月|1200|690|480|\n",
      "|5|内蒙古|其他地区|800|460|320|二连浩特市|7-9月|1000|580|400|\n",
      "|5|内蒙古|其他地区|800|460|320|额济纳旗|9-10月|1200|690|480|\n",
      "|6|辽宁|沈阳市|800|480|350||||||\n",
      "|6|辽宁|其他地区|800|480|330||||||\n",
      "|7|大连|全市|800|490|350|全市|7-9月|960|590|420|\n",
      "|8|吉林|长春市、吉林市、延边州、长白山管理区|800|450|350|吉林市、延边州、长白山管理区|7-9月|960|540|420|\n",
      "|8|吉林|其他地区|750|400|300||||||\n",
      "|9|黑龙江|哈尔滨市|800|450|350|哈尔滨市|7-9月|960|540|420|\n",
      "|9|黑龙江|其他地区|750|450|300|牡丹江市、伊春市、大兴安岭地区、黑河市、佳木斯市|6-8月|900|540|360|\n",
      "|10|上海|全市|1100|600|500||||||\n",
      "|11|江苏|南京市、苏州市、无锡市、常州市、镇江市|900|490|380||||||\n",
      "|11|江苏|其他地区|900|490|360||||||\n",
      "|12|浙江|杭州市|900|500|400||||||\n",
      "|12|浙江|其他地区|800|490|340||||||\n",
      "|13|宁波|全市|800|450|350||||||\n",
      "|14|安徽|全省|800|460|350||||||\n",
      "|15|福建|福州市、泉州市、平潭综合实验区|900|480|380||||||\n",
      "|15|福建|其他地区|900|480|350||||||\n",
      "|16|厦门|全市|900|500|400||||||\n",
      "|17|江西|全省|800|470|350||||||\n",
      "|18|山东|济南市、淄博市、枣庄市、东营市、烟台市、潍坊市、济宁市、泰安市、威海市、日照市|800|480|380|烟台市、威海市、日照市|7-9月|960|570|450|\n",
      "|18|山东|其他地区|800|460|360||||||\n",
      "|19|青岛|全市|800|490|380|全市|7-9月|960|590|450|\n",
      "|20|河南|郑州市|900|480|380||||||\n",
      "|20|河南|其他地区|800|480|330|洛阳市|4-5月上旬|1200|720|500|\n",
      "|21|湖北|武汉市|800|480|350||||||\n",
      "|21|湖北|其他地区|800|480|320||||||\n",
      "|22|湖南|长沙市|800|450|350||||||\n",
      "|22|湖南|其他地区|800|450|330||||||\n",
      "|23|广东|广州市、珠海市、佛山市、东莞市、中山市、江门市|900|550|450||||||\n",
      "|23|广东|其他地区|850|530|420||||||\n",
      "|24|深圳|全市|900|550|450||||||\n",
      "|25|广西|南宁市|800|470|350||||||\n",
      "|25|广西|其他地区|800|470|330|桂林市、北海市|1-2月、7-9月|1040|610|430|\n",
      "|26|海南|海口市、三沙市、儋州市、五指山市、文昌市、琼海市、万宁市、东方市、定安县、屯昌县、澄迈县、临高县、白沙县、昌江县、乐东县、陵水县、保亭县、琼中县、洋浦开发区|800|500|350|海口市、文昌市、澄迈县|11-2月|1040|650|450|\n",
      "|26|海南|海口市、三沙市、儋州市、五指山市、文昌市、琼海市、万宁市、东方市、定安县、屯昌县、澄迈县、临高县、白沙县、昌江县、乐东县、陵水县、保亭县、琼中县、洋浦开发区|800|500|350|琼海市、万宁市、陵水县、保亭县|11-3月|1040|650|450|\n",
      "|26|海南|三亚市|1000|600|400|三亚市|10-4月|1200|720|480|\n",
      "|27|重庆|9个中心城区、北部新区|800|480|370||||||\n",
      "|27|重庆|其他地区|770|450|300||||||\n",
      "|28|四川|成都市|900|470|370||||||\n",
      "|28|四川|阿坝州、甘孜州|800|430|330||||||\n",
      "|28|四川|绵阳市、乐山市、雅安市|800|430|320||||||\n",
      "|28|四川|宜宾市|800|430|300||||||\n",
      "|28|四川|凉山州|750|430|330||||||\n",
      "|28|四川|德阳市、遂宁市、巴中市|750|430|310||||||\n",
      "|28|四川|其他地区|750|430|300||||||\n",
      "|29|贵州|贵阳市|800|470|370||||||\n",
      "|29|贵州|其他地区|750|450|300||||||\n",
      "|30|云南|昆明市、大理州、丽江市、迪庆州、西双版纳州|900|480|380||||||\n",
      "|30|云南|其他地区|900|480|330||||||\n",
      "|31|西藏|拉萨市|800|500|350|拉萨市|6-9月|1200|750|530|\n",
      "|31|西藏|其他地区|500|400|300|其他地区|6-9月|800|500|350|\n",
      "|32|陕西|西安市|800|460|350||||||\n",
      "|32|陕西|榆林市、延安市|680|350|300||||||\n",
      "|32|陕西|杨凌区|680|320|260||||||\n",
      "|32|陕西|咸阳市、宝鸡市|600|320|260||||||\n",
      "|32|陕西|渭南市、韩城市|600|300|260||||||\n",
      "|32|陕西|其他地区|600|300|230||||||\n",
      "|33|甘肃|兰州市|800|470|350||||||\n",
      "|33|甘肃|其他地区|700|450|310||||||\n",
      "|34|青海|西宁市|800|500|350|西宁市|6-9月|1200|750|530|\n",
      "|34|青海|玉树州、果洛州|600|350|300|玉树州|5-9月|900|525|450|\n",
      "|34|青海|海北州、黄南州|600|350|250|海北州、黄南州|5-9月|900|525|375|\n",
      "|34|青海|海东市、海南州|600|300|250|海东市、海南州|5-9月|900|450|375|\n",
      "|34|青海|海西州|600|300|200|海西州|5-9月|900|450|300|\n",
      "|35|宁夏|银川市|800|470|350||||||\n",
      "|35|宁夏|其他地区|800|430|330||||||\n",
      "|36|新疆|乌鲁木齐市|800|480|350||||||\n",
      "|36|新疆|石河子市、克拉玛依市、昌吉州、伊犁州、阿勒泰地区、博州、吐鲁番市、哈密地区、巴州、和田地区|800|480|340||||||\n",
      "|36|新疆|克州|800|480|320||||||\n",
      "|36|新疆|喀什地区|780|480|300||||||\n",
      "|36|新疆|阿克苏地区|700|450|300||||||\n",
      "|36|新疆|塔城地区|700|400|300||||||\n"
     ]
    }
   ],
   "source": [
    "for doc in ret_docs:\n",
    "    print(\"#\"*100)\n",
    "    print(doc.page_content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 160,
   "id": "400fb3fe-e6a1-4ff4-ab6b-d506054e188d",
   "metadata": {},
   "outputs": [],
   "source": [
    "embedding_retriever = zhidu_db.as_retriever(search_kwargs={\"k\": 3})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 161,
   "id": "dd1a302c-a698-4936-bc6a-0ea924aeabc5",
   "metadata": {},
   "outputs": [],
   "source": [
    "ensemble_retriever = EnsembleRetriever(\n",
    "    retrievers=[bm25_retriever, embedding_retriever], weights=[0.3, 0.7]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 162,
   "id": "67240596-7031-4961-b548-faaf7aaf2c36",
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"公司丧假有什么规定？\"\n",
    "related_docs = ensemble_retriever.invoke(query)[:3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 163,
   "id": "b8014ce0-2f32-4d66-ad4c-8cf5ef6de364",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "####################################################################################################\n",
      "（1）婚假期间员工工资照发。\n",
      "（2）为了保证教学活动的顺利进行，提倡婚假安排在寒暑假。\n",
      "4、丧假：员工因配偶或直系亲属丧亡时，可申请丧假：配偶、父母（公婆、岳父母）、子女及其配偶、祖父母、外祖父母、孙子女（外孙子女）及其配偶、曾祖父母、曾外祖父母丧亡，丧假3 天。\n",
      "5、产假：符合计划生育政策规定的女性员工可享受产假\n",
      "####################################################################################################\n",
      "第三节休假规定\n",
      "休假分以下八种：事假、病假、婚假、丧假、产假、哺乳假、工伤假、调休。1、事假：（1）请假必须严格按照学校规定的请假程序，应由本人以书面形式，应在前两日办理手续，特殊情况应通过电话或者口头请假，应在事假结束于2 个工作日内完成补办请假手续。未经请假或请假未准而擅自离岗者，以旷工论处。（2）事假最小计算单位为半天，事假一次不得超过3 天。（3）事假：基本工资和岗位津贴均按请假天数占实际上班天数比例来算。（4）请假理由不充分或致工作妨碍时，可酌情缩短假期、或延期给假、或不予给假。（5）请假者必须将所任课务或经办事务交待给代理人员，并于请假单内注明。\n",
      "2、病假：因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。（1）教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，应在病假结束于2 个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。(2)病假按照工龄系数，对病假日工资进行扣除。\n",
      "<table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table>\n",
      "3、婚假：全体教职工达到国家法律（男方22 周岁，女方20 周岁）规定的，经过法定程序办理结婚手续的，可凭结婚证申请婚假15 天（均含休息日）。\n",
      "####################################################################################################\n",
      "。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请\n"
     ]
    }
   ],
   "source": [
    "for doc in related_docs:\n",
    "    print(\"#\"*100)\n",
    "    print(doc.page_content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 170,
   "id": "be61dc41-6f62-4133-9a25-725bc3279ba9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "####################################################################################################\n",
      "query: 公司丧假有什么规定？\n",
      "context: 上下文1: （1）婚假期间员工工资照发。\n",
      "（2）为了保证教学活动的顺利进行，提倡婚假安排在寒暑假。\n",
      "4、丧假：员工因配偶或直系亲属丧亡时，可申请丧假：配偶、父母（公婆、岳父母）、子女及其配偶、祖父母、外祖父母、孙子女（外孙子女）及其配偶、曾祖父母、曾外祖父母丧亡，丧假3 天。\n",
      "5、产假：符合计划生育政策规定的女性员工可享受产假 \n",
      "\n",
      "上下文2: 第三节休假规定\n",
      "休假分以下八种：事假、病假、婚假、丧假、产假、哺乳假、工伤假、调休。1、事假：（1）请假必须严格按照学校规定的请假程序，应由本人以书面形式，应在前两日办理手续，特殊情况应通过电话或者口头请假，应在事假结束于2 个工作日内完成补办请假手续。未经请假或请假未准而擅自离岗者，以旷工论处。（2）事假最小计算单位为半天，事假一次不得超过3 天。（3）事假：基本工资和岗位津贴均按请假天数占实际上班天数比例来算。（4）请假理由不充分或致工作妨碍时，可酌情缩短假期、或延期给假、或不予给假。（5）请假者必须将所任课务或经办事务交待给代理人员，并于请假单内注明。\n",
      "2、病假：因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。（1）教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，应在病假结束于2 个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。(2)病假按照工龄系数，对病假日工资进行扣除。\n",
      "<table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table>\n",
      "3、婚假：全体教职工达到国家法律（男方22 周岁，女方20 周岁）规定的，经过法定程序办理结婚手续的，可凭结婚证申请婚假15 天（均含休息日）。 \n",
      "\n",
      "上下文3: 。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请 \n",
      "\n",
      "response: \n",
      "公司丧假规定如下：员工因配偶、父母（包括公婆、岳父母）、子女及其配偶、祖父母、外祖父母、孙子女（外孙子女）及其配偶、曾祖父母、曾外祖父母丧亡时，可申请3天的丧假。"
     ]
    },
    {
     "data": {
      "text/plain": [
       "''"
      ]
     },
     "execution_count": 170,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "run_rag_pipline(query, related_docs, k=3, context_query_type=\"doc\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f05b23c9-829e-4b3c-a58c-0c33c14cac9f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ce045e2f-b108-495d-bf2b-d4bc11102ac9",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6eb6866f-09cd-4375-9901-7c60ac6fcdef",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8517cdcc-2ece-48f2-8fa9-f5a1206fa4d5",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7288fdba-1ae1-4f7a-a166-e4e7f6c9b673",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9d9a4eef-5a06-4d60-9d06-552daf77138c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9824dbcf-a831-453c-a772-cc35a0b66b74",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "ec7afacd-7a98-4bfa-8061-95089288b9c6",
   "metadata": {
    "tags": []
   },
   "source": [
    "## rerank"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 171,
   "id": "4464fc10-26fe-4ed3-bdfa-7b3fd4168e5e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "os.environ['CUDA_VISIBLE_DEVICES'] = '1'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 172,
   "id": "ae467adf-3569-4a11-8222-79a1f7ab2e28",
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import AutoModelForSequenceClassification, AutoTokenizer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 173,
   "id": "affc2e6f-43d4-477d-8681-d5e9d69b5ba7",
   "metadata": {},
   "outputs": [],
   "source": [
    "model_path = './data/llm_app/embedding_models/bge-reranker-base/'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 174,
   "id": "37b2a5cb-0e96-47fb-a35f-37019bfbdb97",
   "metadata": {},
   "outputs": [],
   "source": [
    "tokenizer = AutoTokenizer.from_pretrained(model_path)\n",
    "rerank_model = AutoModelForSequenceClassification.from_pretrained(model_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 175,
   "id": "cb409399-4897-41fd-9444-025010a676e0",
   "metadata": {},
   "outputs": [],
   "source": [
    "rerank_model = rerank_model.cuda()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 176,
   "id": "dac5db31-b9e5-40bf-af83-d1b5a77413ec",
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"我要请病假100天\"\n",
    "ret_docs = bm25_retriever.invoke(query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 185,
   "id": "4b763a25-a67a-471b-87b5-c2a3cbe1de8d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Document(metadata={'type': 'ori', 'is_table': 1}, page_content='<table><caption>伙食补助费参考以下标准：</caption>\\n<tr><td  >地区</td><td  >伙食补助费标准</td></tr>\\n<tr><td  >西藏、青海、新疆</td><td  >120 元/人、天</td></tr>\\n<tr><td  >其他省份</td><td  >100 元/人、天</td></tr>\\n</table>'),\n",
       " Document(metadata={'type': 'ori', 'is_table': 1}, page_content='2\\n<table><caption>伙食补助费参考以下标准：</caption>\\n<tr><td  >地区</td><td  >伙食补助费标准</td></tr>\\n<tr><td  >西藏、青海、新疆</td><td  >120 元/人、天</td></tr>\\n<tr><td  >其他省份</td><td  >100 元/人、天</td></tr>\\n</table>'),\n",
       " Document(metadata={'type': 'ori', 'is_table': 1}, page_content='第三节休假规定\\n休假分以下八种：事假、病假、婚假、丧假、产假、哺乳假、工伤假、调休。1、事假：（1）请假必须严格按照学校规定的请假程序，应由本人以书面形式，应在前两日办理手续，特殊情况应通过电话或者口头请假，应在事假结束于2 个工作日内完成补办请假手续。未经请假或请假未准而擅自离岗者，以旷工论处。（2）事假最小计算单位为半天，事假一次不得超过3 天。（3）事假：基本工资和岗位津贴均按请假天数占实际上班天数比例来算。（4）请假理由不充分或致工作妨碍时，可酌情缩短假期、或延期给假、或不予给假。（5）请假者必须将所任课务或经办事务交待给代理人员，并于请假单内注明。\\n2、病假：因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。（1）教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，应在病假结束于2 个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。(2)病假按照工龄系数，对病假日工资进行扣除。\\n<table><caption>病假发放标准：</caption>\\n<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\\n<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\\n<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\\n<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\\n<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\\n<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\\n<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\\n<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\\n<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\\n</table>\\n3、婚假：全体教职工达到国家法律（男方22 周岁，女方20 周岁）规定的，经过法定程序办理结婚手续的，可凭结婚证申请婚假15 天（均含休息日）。')]"
      ]
     },
     "execution_count": 185,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ret_docs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 186,
   "id": "77035203-f6d4-41b3-ab88-4babcef6b002",
   "metadata": {},
   "outputs": [],
   "source": [
    "pairs = []\n",
    "for doc in ret_docs:\n",
    "    pairs.append([query, doc.page_content])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 187,
   "id": "6ab16fcc-d6c1-4d8d-afff-8c08c3c4dfb2",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "inputs = tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512)\n",
    "\n",
    "with torch.no_grad():\n",
    "    inputs = {key: inputs[key].cuda() for key in inputs.keys()}\n",
    "    scores = rerank_model(**inputs, return_dict=True).logits.view(-1, ).float()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 188,
   "id": "4cf84725-6e41-4919-b0e5-ad5b104f44db",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([-4.0480, -4.0110,  0.5134], device='cuda:0')"
      ]
     },
     "execution_count": 188,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "scores"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 189,
   "id": "e505e4d5-db57-4d84-b463-a3f1f63db337",
   "metadata": {},
   "outputs": [],
   "source": [
    "doc_sort_ids = list((scores.cpu().numpy()*-1).argsort())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 190,
   "id": "a5344322-9425-43e7-8cd7-1b204281e339",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 1, 0]"
      ]
     },
     "execution_count": 190,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "doc_sort_ids"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 193,
   "id": "a35818c6-fa14-4c21-b86c-bb7f281256aa",
   "metadata": {},
   "outputs": [],
   "source": [
    "adocs = [np.array(ret_docs)[doc_sort_ids][0]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 194,
   "id": "554453b9-c293-4acc-a3af-8c8e6e61c7d6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "####################################################################################################\n",
      "query: 我要请病假100天\n",
      "context: 上下文1: 第三节休假规定\n",
      "休假分以下八种：事假、病假、婚假、丧假、产假、哺乳假、工伤假、调休。1、事假：（1）请假必须严格按照学校规定的请假程序，应由本人以书面形式，应在前两日办理手续，特殊情况应通过电话或者口头请假，应在事假结束于2 个工作日内完成补办请假手续。未经请假或请假未准而擅自离岗者，以旷工论处。（2）事假最小计算单位为半天，事假一次不得超过3 天。（3）事假：基本工资和岗位津贴均按请假天数占实际上班天数比例来算。（4）请假理由不充分或致工作妨碍时，可酌情缩短假期、或延期给假、或不予给假。（5）请假者必须将所任课务或经办事务交待给代理人员，并于请假单内注明。\n",
      "2、病假：因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。（1）教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，应在病假结束于2 个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。(2)病假按照工龄系数，对病假日工资进行扣除。\n",
      "<table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table>\n",
      "3、婚假：全体教职工达到国家法律（男方22 周岁，女方20 周岁）规定的，经过法定程序办理结婚手续的，可凭结婚证申请婚假15 天（均含休息日）。 \n",
      "\n",
      "response: \n",
      "根据公司规定，病假发放标准与连续工龄有关。对于6个月以上的长期病假，不满一年的员工按40%发放工资，已满一年不满三年的按50%，而连续工龄三年以上的则按60%发放。由于您提出请100天即超过3个月的病假，需要提供三级医院开具的病假条或诊断证明，并且根据您的具体工龄来确定工资发放比例。\n",
      "\n",
      "请注意，在紧急或突发情况下无法提前请假时，应通过电话或者口头请假，并在病假结束后的2个工作日内补办相关手续。未经批准擅自离岗将被视为旷工处理。\n",
      "如果您需要请长期病假，请确保按照规定流程申请并提供必要的医疗证明。"
     ]
    },
    {
     "data": {
      "text/plain": [
       "''"
      ]
     },
     "execution_count": 194,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "run_rag_pipline(query, adocs, k=3, context_query_type=\"doc\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e2d38caf-5421-4447-bd03-75710bcc0607",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d3c43b1-5509-4255-9d99-d871f0b70cb9",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6408e5a4-4a86-4641-a579-b6d87540e68e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "c11461b4-acb4-4423-a613-11c26e64fdfb",
   "metadata": {
    "tags": []
   },
   "source": [
    "## 迭代检索增强生成"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 195,
   "id": "79305ead-3733-4257-b721-190a79896c71",
   "metadata": {},
   "outputs": [],
   "source": [
    "iter_retgen_prompt_template = \"\"\"\n",
    "你是企业员工助手，熟悉公司考勤和报销标准等规章制度，需要参考提供的上下文信息context来回答员工的提问。\\\n",
    "请直接回答问题，如果上下文信息context没有和问题相关的信息，可尝试回答 \\\n",
    "问题：{question} \n",
    "\"{context}\"\n",
    "回答：\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 197,
   "id": "14f38d2a-e3d6-49d7-9c14-3bac3aab3488",
   "metadata": {},
   "outputs": [],
   "source": [
    "def iter_retgen(query, iter_num=2):\n",
    "    iter_answer = None\n",
    "    for i in range(iter_num):\n",
    "        context_query = f\"{query}, {iter_answer}\" if iter_answer else query\n",
    "        print(\"=\"*50, \"context query-\", i, \"=\"*50)\n",
    "        print(context_query)\n",
    "        \n",
    "        if i < iter_num - 1:\n",
    "            iter_answer = run_rag_pipline(query, context_query, k=3, context_query_type=\"query\", \n",
    "                                          stream=False, \n",
    "                                          prompt_template=iter_retgen_prompt_template,\n",
    "                                          temperature=1.1)\n",
    "            print(\"=\"*50, \"iter-\", i, \"=\"*50)\n",
    "            print(iter_answer)\n",
    "        else:\n",
    "            iter_answer = run_rag_pipline(query, context_query, k=3, context_query_type=\"query\", \n",
    "                              stream=True, \n",
    "                              prompt_template=prompt_template,\n",
    "                              temperature=0.1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 200,
   "id": "e2f93955-b730-4ab9-b76c-d3badd20ef43",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================================== context query- 0 ==================================================\n",
      "公司的假有哪些，规定是什么？\n",
      "\n",
      "\n",
      "####################################################################################################\n",
      "query: 公司的假有哪些，规定是什么？\n",
      "context: 上下文1: 第三节休假规定\n",
      "休假分以下八种：事假、病假、婚假、丧假、产假、哺乳假、工伤假、调休。1、事假：（1）请假必须严格按照学校规定的请假程序，应由本人以书面形式，应在前两日办理手续，特殊情况应通过电话或者口头请假，应在事假结束于2 个工作日内完成补办请假手续。未经请假或请假未准而擅自离岗者，以旷工论处。（2）事假最小计算单位为半天，事假一次不得超过3 天。（3）事假：基本工资和岗位津贴均按请假天数占实际上班天数比例来算。（4）请假理由不充分或致工作妨碍时，可酌情缩短假期、或延期给假、或不予给假。（5）请假者必须将所任课务或经办事务交待给代理人员，并于请假单内注明。\n",
      "2、病假：因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。（1）教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，应在病假结束于2 个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。(2)病假按照工龄系数，对病假日工资进行扣除。\n",
      "<table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table>\n",
      "3、婚假：全体教职工达到国家法律（男方22 周岁，女方20 周岁）规定的，经过法定程序办理结婚手续的，可凭结婚证申请婚假15 天（均含休息日）。 \n",
      "\n",
      "上下文2: 。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请 \n",
      "\n",
      "上下文3: ⑹假满未经续假或未被同意续假的，或无出差审批手续的；\n",
      "⑺不服从学校应工作需要进行的正常调动和分配，有岗不上的；\n",
      "⑻以公出或病、事假为由，工作时间在外干私活的；⑼其它法律规定的情形。\n",
      "4.违规处理 \n",
      "\n",
      "================================================== iter- 0 ==================================================\n",
      "公司规定的假期类型主要包括以下几种：\n",
      "\n",
      "1. **事假**：必须按照规定流程书面申请。事假至少以半天计，单次不超过3天。未经批准离岗视为旷工。\n",
      "\n",
      "2. **病假**：因健康原因需要休病假的员工应提前申请，紧急情况可先电话请假再补手续。病假发放标准根据连续工龄计算：\n",
      "\n",
      "   - 不满二年为60%\n",
      "   - 已满二年不满四年为70%\n",
      "   - 四年至六年为80%\n",
      "   - 六至八年为90%\n",
      "   - 八年以上为100%\n",
      "   - 一年以下的员工病假6个月以上为40%，一至三年间则为50%，连续工龄三年以上的发放标准是60%。\n",
      "\n",
      "3. **婚假**：达到法定结婚年龄，持有合法婚姻证明可申请15天的婚假（包括休息日）。\n",
      "\n",
      "除上述假期外，公司还提供其他类型休假如丧假、产假、哺乳假、工伤假和调休。员工需遵循请假流程，在钉钉系统中提交请假申请，并确保符合相关公司的规章制度以避免违规处理。具体假期时长和详细规则请参照各类型假期的具体规定。\n",
      "\n",
      "如有疑问或需要进一步信息，欢迎咨询人力资源部或其他相关部门。\n",
      "================================================== context query- 1 ==================================================\n",
      "公司的假有哪些，规定是什么？, 公司规定的假期类型主要包括以下几种：\n",
      "\n",
      "1. **事假**：必须按照规定流程书面申请。事假至少以半天计，单次不超过3天。未经批准离岗视为旷工。\n",
      "\n",
      "2. **病假**：因健康原因需要休病假的员工应提前申请，紧急情况可先电话请假再补手续。病假发放标准根据连续工龄计算：\n",
      "\n",
      "   - 不满二年为60%\n",
      "   - 已满二年不满四年为70%\n",
      "   - 四年至六年为80%\n",
      "   - 六至八年为90%\n",
      "   - 八年以上为100%\n",
      "   - 一年以下的员工病假6个月以上为40%，一至三年间则为50%，连续工龄三年以上的发放标准是60%。\n",
      "\n",
      "3. **婚假**：达到法定结婚年龄，持有合法婚姻证明可申请15天的婚假（包括休息日）。\n",
      "\n",
      "除上述假期外，公司还提供其他类型休假如丧假、产假、哺乳假、工伤假和调休。员工需遵循请假流程，在钉钉系统中提交请假申请，并确保符合相关公司的规章制度以避免违规处理。具体假期时长和详细规则请参照各类型假期的具体规定。\n",
      "\n",
      "如有疑问或需要进一步信息，欢迎咨询人力资源部或其他相关部门。\n",
      "\n",
      "\n",
      "####################################################################################################\n",
      "query: 公司的假有哪些，规定是什么？\n",
      "context: 上下文1: 第三节休假规定\n",
      "休假分以下八种：事假、病假、婚假、丧假、产假、哺乳假、工伤假、调休。1、事假：（1）请假必须严格按照学校规定的请假程序，应由本人以书面形式，应在前两日办理手续，特殊情况应通过电话或者口头请假，应在事假结束于2 个工作日内完成补办请假手续。未经请假或请假未准而擅自离岗者，以旷工论处。（2）事假最小计算单位为半天，事假一次不得超过3 天。（3）事假：基本工资和岗位津贴均按请假天数占实际上班天数比例来算。（4）请假理由不充分或致工作妨碍时，可酌情缩短假期、或延期给假、或不予给假。（5）请假者必须将所任课务或经办事务交待给代理人员，并于请假单内注明。\n",
      "2、病假：因身体健康问题不能正常工作的员工可申请病假，休假后须提供三级医院开具的病假条或诊断证明。（1）教职工休病假需提前申请。如因情况紧急或突发情况无法请假的，应通过电话或者口头请假，应在病假结束于2 个工作日内补办相关手续。未经请假或请假未准而擅自离岗者，以旷工论处。(2)病假按照工龄系数，对病假日工资进行扣除。\n",
      "<table><caption>病假发放标准：</caption>\n",
      "<tr><td  >病假时间</td><td  >连续工龄</td><td  >发放标准</td></tr>\n",
      "<tr><td></td><td  >不满二年</td><td  >60% </td></tr>\n",
      "<tr><td></td><td  >已满二年不满四年</td><td  >70% </td></tr>\n",
      "<tr><td  >6 个月以内病假</td><td  >已满四年不满六年</td><td  >80% </td></tr>\n",
      "<tr><td></td><td  >已满六年不满八年</td><td  >90% </td></tr>\n",
      "<tr><td></td><td  >八年以上</td><td  >100% </td></tr>\n",
      "<tr><td></td><td  >不满一年</td><td  >40% </td></tr>\n",
      "<tr><td  >6 个月以上病假</td><td  >已满一年不满三年</td><td  >50% </td></tr>\n",
      "<tr><td></td><td  >连续工龄三年以上</td><td  >60% </td></tr>\n",
      "</table>\n",
      "3、婚假：全体教职工达到国家法律（男方22 周岁，女方20 周岁）规定的，经过法定程序办理结婚手续的，可凭结婚证申请婚假15 天（均含休息日）。 \n",
      "\n",
      "上下文2: 。原则上，员工请假无论时间长短、假期形式，除急诊病假或突发事件外，一律需按照请假流程。请假，需事先在钉钉系统中提交申请 \n",
      "\n",
      "上下文3: 。请假，需事先在钉钉系统中提交申请。有效的请假流程为：（1）员工休假必须事先向部门负责人申请，将工作交接清楚方可休假；（2）2 天以内的假期必须经过部门分管领导审批；（3）3 天以上的假期必须经过校长审批 \n",
      "\n",
      "response: \n",
      "公司规定的假种包括事假、病假、婚假、丧假、产假、哺乳假、工伤假和调休。具体规定如下：\n",
      "\n",
      "1. **事假**：需提前书面申请，特殊情况可先电话请假后补办手续。最小计算单位为半天，一次不得超过3天。工资按请假天数比例扣除。\n",
      "\n",
      "2. **病假**：因健康问题无法工作时可请，需提供三级医院证明。紧急情况可先口头请假再补手续。发放标准根据工龄不同而异，从60%到100%不等。\n",
      "\n",
      "3. **婚假**：符合法定结婚年龄的员工凭结婚证可申请15天假期（含休息日）。\n",
      "\n",
      "4. **丧假、产假、哺乳假和工伤假**的具体规定未在上下文中提及，请参考公司完整的人力资源手册或向人力资源部门咨询。\n",
      "\n",
      "所有请假需通过钉钉系统提交，并遵循审批流程：2天以内由部门分管领导审批，3天以上需校长审批。紧急情况除外，但事后仍需补办手续。\n",
      "  \n",
      "请注意，具体细节可能根据公司的最新政策有所调整，请以公司最新的人力资源管理规定为准。"
     ]
    }
   ],
   "source": [
    "query = \"公司的假有哪些，规定是什么？\"\n",
    "iter_retgen(query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c14369f7-488f-4788-91af-a54831d5129a",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "10abea8a-baaf-448f-8003-4468d1477900",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9f6d2e71-ae18-41e7-a097-c257dd996ce6",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d7b82ae4-0e7d-4e44-8ab0-9c4a041973ae",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3689f75b-0368-41c3-8b55-4e29f8768e1b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f1f26364-e276-4704-8f05-1f0519dc64c5",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a3ebdb8d-175f-499f-8eed-1edf47fa6a2b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "18e6df88-47f7-496e-bb62-94c1c2593c8d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "fd8b44b0-57dc-43be-8811-9c95270874b1",
   "metadata": {
    "tags": []
   },
   "source": [
    "## self-RAG\n",
    "- 使用langgraph来实现；\n",
    "- LangGraph 通过节点（Nodes）和边（Edges）来定义工作流，其中每个节点可以执行特定的任务，而边则定义了数据如何在这些任务之间流动"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51ca20d7-80e0-4b7b-877c-b218bdef214f",
   "metadata": {},
   "source": [
    "![](./data/selfrag.drawio.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 201,
   "id": "df04858a-1de4-4d7d-a7cb-9268e07b5c52",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts import PromptTemplate\n",
    "from langchain_core.output_parsers import StrOutputParser"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 202,
   "id": "95c732a0-a41a-4214-8861-da19e0bae521",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import Dict, TypedDict\n",
    "from typing_extensions import TypedDict\n",
    "from langgraph.graph import END, StateGraph\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 203,
   "id": "6d7288d9-6069-4684-a09a-1d7658e33a3d",
   "metadata": {},
   "outputs": [],
   "source": [
    "def rag_retrieve(question, k=3):\n",
    "    related_docs = zhidu_db.similarity_search(question, k=3)\n",
    "    context = \"\\n\".join([f\"上下文{i+1}: {doc.page_content} \\n\" \\\n",
    "                         for i, doc in enumerate(related_docs)])\n",
    "    return related_docs, context"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 205,
   "id": "53969852-4171-4ad2-b1eb-4847da9c17b8",
   "metadata": {},
   "outputs": [],
   "source": [
    "def retrieve(state):\n",
    "\n",
    "    print(\"---retrieve---\")\n",
    "    # node input \n",
    "    state_dict = state[\"keys\"]\n",
    "    question = state_dict[\"question\"]\n",
    "    context_query = state_dict.get(\"context_query\", None)\n",
    "    query2doc_count = state_dict.get(\"query2doc_count\", 0)\n",
    "    rewrite_count = state_dict.get(\"rewrite_count\", 0)\n",
    "    \n",
    "    # task\n",
    "    if context_query is not None:\n",
    "        documents, context = rag_retrieve(context_query, k=3)\n",
    "    else:\n",
    "        documents, context = rag_retrieve(question, k=3)\n",
    "        \n",
    "    # node output\n",
    "    return {\"keys\": {\"context\": context, \n",
    "                     \"question\": question, \n",
    "                     \"documents\": documents,\n",
    "                     \"query2doc_count\": query2doc_count,\n",
    "                     \"rewrite_count\": rewrite_count}}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 206,
   "id": "efefd3ec-3b3b-48ce-9f15-27effe179a81",
   "metadata": {},
   "outputs": [],
   "source": [
    "def transform_query2doc(state):\n",
    "    print(\"---transform_query2doc---\")\n",
    "    state_dict = state[\"keys\"]\n",
    "    question = state_dict[\"question\"]\n",
    "    documents = state_dict[\"documents\"]\n",
    "    context = state_dict[\"context\"]\n",
    "    query2doc_count = state_dict.get(\"query2doc_count\", 0)\n",
    "    rewrite_count = state_dict.get(\"rewrite_count\", 0)\n",
    "    \n",
    "\n",
    "    context_query = query2doc(question)\n",
    "    return {\"keys\": {\"context\": context,\n",
    "                     \"documents\": documents, \n",
    "                     \"question\": question, \n",
    "                     \"context_query\": context_query, \n",
    "                     \"query2doc_count\": query2doc_count+1,\n",
    "                     \"rewrite_count\": rewrite_count}}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 207,
   "id": "42992d35-0340-42bc-ba9f-ffead6f6ab00",
   "metadata": {},
   "outputs": [],
   "source": [
    "def transform_query_rewrite(state):\n",
    "    print(\"---transform_query---\")\n",
    "    state_dict = state[\"keys\"]\n",
    "    question = state_dict[\"question\"]\n",
    "    documents = state_dict[\"documents\"]\n",
    "    context = state_dict[\"context\"]\n",
    "    query2doc_count = state_dict.get(\"query2doc_count\", 0)\n",
    "    rewrite_count = state_dict.get(\"rewrite_count\", 0)\n",
    "    \n",
    "\n",
    "    context_query = question_rewrite(question)\n",
    "    \n",
    "    return {\"keys\": {\"context\": context,\n",
    "                     \"documents\": documents, \n",
    "                     \"question\": question, \n",
    "                     \"context_query\": context_query,\n",
    "                     \"query2doc_count\": query2doc_count,\n",
    "                     \"rewrite_count\": rewrite_count+1}}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 208,
   "id": "1a29c9fe-3909-4040-a04e-0f617f83bed6",
   "metadata": {},
   "outputs": [],
   "source": [
    "def generate(state):\n",
    "\n",
    "    print(\"---Generate answer---\")\n",
    "    state_dict = state[\"keys\"]\n",
    "    question = state_dict[\"question\"]\n",
    "    documents = state_dict[\"documents\"]\n",
    "    query2doc_count = state_dict.get(\"query2doc_count\", 0)\n",
    "    rewrite_count = state_dict.get(\"rewrite_count\", 0)\n",
    "    \n",
    "    # context\n",
    "    context = \"\\n\".join([f\"上下文{i+1}: {doc.page_content} \\n\" \\\n",
    "                         for i, doc in enumerate(documents)])\n",
    "    \n",
    "    # Prompt\n",
    "    prompt = PromptTemplate(\n",
    "                        input_variables=[\"question\", \"context\"],\n",
    "                        template=prompt_template,)\n",
    "    llm_prompt = prompt.format(question=query, context=context)\n",
    "\n",
    "    # LLM\n",
    "    llm = langchain_llm\n",
    "\n",
    "    # Chain\n",
    "    rag_chain = prompt | llm | StrOutputParser()\n",
    "    \n",
    "    # Run\n",
    "    generation = rag_chain.invoke({\"context\": context, \"question\": question})\n",
    "    return {\n",
    "        \"keys\": {\"context\": context, \n",
    "                 \"question\": question, \n",
    "                 \"documents\": documents, \n",
    "                 \"generation\": generation,\n",
    "                 \"query2doc_count\": query2doc_count,\n",
    "                 \"rewrite_count\": rewrite_count\n",
    "                }\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 209,
   "id": "94c71f43-b77a-415d-bf39-20bcc86f9a78",
   "metadata": {},
   "outputs": [],
   "source": [
    "context_grade_prompt = PromptTemplate(\n",
    "    template=\"\"\"您是一名评分员，针对公司规章的问题，负责评估检索到的文档与用户问题的相关性。\\n \n",
    "    以下是检索到的文档: \\n\\n {context} \\n\\n\n",
    "    以下是用户问题: {question} \\n\n",
    "    如果文档包含与用户问题相关的关键词或语义信息，请将其评为相关. \\n\n",
    "    请给出一个二元分类 'Yes' 或 'No'，以指示该文档是否与问题相关.\"\"\",\n",
    "    input_variables=[\"context\", \"question\"],\n",
    ")\n",
    "\n",
    "context_grade_chain = context_grade_prompt | langchain_llm | StrOutputParser()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 210,
   "id": "58fc6d82-1ab9-4bac-9557-01b56bc9c005",
   "metadata": {},
   "outputs": [],
   "source": [
    "answer_useful_prompt = PromptTemplate(\n",
    "                        template=\"\"\"您是一名评分员，针对公司规章的问题，负责评估一个答案是否对解决用户问题有用。\\n \n",
    "                        以下是答案: \\n\\n {generation} \\n\\n\n",
    "                        以下是用户问题: {question} \\n\n",
    "                        请给出一个二元分类 'Yes' 或 'No'，以指示答案是否对解决问题有用.\"\"\",\n",
    "                        input_variables=[\"generation\", \"question\"],\n",
    "                    )\n",
    "answer_useful_chain = answer_useful_prompt | langchain_llm | StrOutputParser()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 211,
   "id": "e3403efa-b081-4ff3-8615-65eebf370f76",
   "metadata": {},
   "outputs": [],
   "source": [
    "answer_supported_prompt = PromptTemplate(\n",
    "                        template=\"\"\"您是一名评分员，针对公司规章的问题，负责评估一个答案是否基于或者由一组事实支持。\\n \n",
    "                        以下是事实: \\n\\n {context} \\n\\n\n",
    "                        以下是答案: {generation} \\n\n",
    "                        请给出一个二元分类 'Yes' 或 'No'，以指示答案是否基于或者由一组事实支持.\\n\n",
    "                        不需要前言或解释\"\"\",\n",
    "                        input_variables=[\"context\", \"generation\"],\n",
    "                    )\n",
    "answer_supported_chain = answer_supported_prompt | langchain_llm | StrOutputParser()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 212,
   "id": "781ba626-0dcc-4436-af8d-d076e28c848c",
   "metadata": {},
   "outputs": [],
   "source": [
    "def grade_documents(state):\n",
    "\n",
    "    print(\"---Determines whether the retrieved documents are relevant to the question---\")\n",
    "    state_dict = state[\"keys\"]\n",
    "    question = state_dict[\"question\"]\n",
    "    documents = state_dict[\"documents\"]\n",
    "    context = state_dict[\"context\"]\n",
    "    query2doc_count = state_dict.get(\"query2doc_count\", 0)\n",
    "    rewrite_count = state_dict.get(\"rewrite_count\", 0)\n",
    "    \n",
    "    # Score\n",
    "    filtered_docs = []\n",
    "    retrieve_enhance = \"No\"\n",
    "    for d in documents:\n",
    "        grade = context_grade_chain.invoke({\"question\": question, \"context\": d.page_content})\n",
    "        if  \"yes\" in grade.lower():\n",
    "            print(\"---GRADE: DOCUMENT RELEVANT---\")\n",
    "            filtered_docs.append(d)\n",
    "        else:\n",
    "            print(\"---GRADE: DOCUMENT NOT RELEVANT---\")\n",
    "            retrieve_enhance = \"Yes\"\n",
    "            continue\n",
    "    if query2doc_count > 0:\n",
    "        retrieve_enhance = \"No\"\n",
    "    context = \"\"\n",
    "    if len(filtered_docs):\n",
    "        context = \"\\n\".join([f\"上下文{i+1}: {doc.page_content} \\n\" \\\n",
    "                         for i, doc in enumerate(filtered_docs)])\n",
    "    return {\n",
    "        \"keys\": {\n",
    "            \"context\": context,\n",
    "            \"documents\": filtered_docs,\n",
    "            \"question\": question,\n",
    "            \"run_retrieve_enhance\": retrieve_enhance,\n",
    "            \"query2doc_count\": query2doc_count,\n",
    "            \"rewrite_count\": rewrite_count\n",
    "        }\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 213,
   "id": "4f02b1c1-f2db-4ff2-98f3-f55ab1d4bfc8",
   "metadata": {},
   "outputs": [],
   "source": [
    "def grade_generation_v_documents_and_question(state):\n",
    "    print(\"---Determines whether the answer is relevant to the question---\")\n",
    "    state_dict = state[\"keys\"]\n",
    "    question = state_dict[\"question\"]\n",
    "    documents = state_dict[\"documents\"]\n",
    "    context = state_dict[\"context\"]\n",
    "    query2doc_count = state_dict.get(\"query2doc_count\", 0)\n",
    "    generation = state_dict[\"generation\"]\n",
    "    rewrite_count = state_dict.get(\"rewrite_count\", 0)\n",
    "    \n",
    "    grade = answer_supported_chain.invoke({\"generation\": generation, \"context\": context})\n",
    "    \n",
    "    if \"yes\" in grade.lower():\n",
    "        print(\"---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---\")\n",
    "        # Check question-answering\n",
    "        print(\"---GRADE GENERATION vs QUESTION---\")\n",
    "        score = answer_useful_chain.invoke({\"question\": question, \"generation\": generation})\n",
    "        if \"yes\" in score.lower():\n",
    "            print(\"---DECISION: GENERATION ADDRESSES QUESTION---\")\n",
    "            return \"useful\"\n",
    "        else:\n",
    "            if rewrite_count < 1:\n",
    "                print(\"---DECISION: GENERATION DOES NOT ADDRESS QUESTION---\")\n",
    "                return \"not useful\"\n",
    "            else:\n",
    "                return \"end\"\n",
    "    else:\n",
    "        print(\"---DECISION: GENERATION IS NOT GROUNDED IN DOCUMENTS, RE-TRY---\")\n",
    "        return \"not supported\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 215,
   "id": "779973f6-9ced-4c4e-a60f-8e4ed2dacdd8",
   "metadata": {},
   "outputs": [],
   "source": [
    "def decide_to_generate(state):\n",
    "\n",
    "    print(\"---DECIDE TO GENERATE---\")\n",
    "    state_dict = state[\"keys\"]\n",
    "    question = state_dict[\"question\"]\n",
    "    filtered_documents = state_dict[\"documents\"]\n",
    "    retrieve_enhance = state_dict[\"run_retrieve_enhance\"]\n",
    "    query2doc_count = state_dict.get(\"query2doc_count\", 0)\n",
    "\n",
    "    if retrieve_enhance == \"Yes\":\n",
    "        if query2doc_count > 1:\n",
    "            return \"generate\"\n",
    "        else:\n",
    "            print(\"---DECISION:  transform_query2doc---\")\n",
    "            return \"transform_query2doc\"\n",
    "    else:\n",
    "        print(\"---DECISION: GENERATE---\")\n",
    "        return \"generate\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 216,
   "id": "1663a8fb-4e3b-4031-a674-439e71429b63",
   "metadata": {},
   "outputs": [],
   "source": [
    "class GraphState(TypedDict):\n",
    "    keys: Dict[str, any]\n",
    "workflow = StateGraph(GraphState)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 217,
   "id": "1fa22ba3-73b2-48ba-9156-ea3e67d0b6d5",
   "metadata": {},
   "outputs": [],
   "source": [
    "workflow.add_node(\"retrieve\", retrieve)  # retrieve\n",
    "workflow.add_node(\"grade_documents\", grade_documents)  # grade documents\n",
    "workflow.add_node(\"generate\", generate)  # generatae\n",
    "workflow.add_node(\"transform_query2doc\", transform_query2doc) # query2doc\n",
    "workflow.add_node(\"transform_query_rewrite\", transform_query_rewrite) # query2doc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 218,
   "id": "93687a51-51c1-40f9-adbd-099281071286",
   "metadata": {},
   "outputs": [],
   "source": [
    "workflow.set_entry_point(\"retrieve\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 219,
   "id": "72394e0d-83b5-4935-b248-691ff7f4b85f",
   "metadata": {},
   "outputs": [],
   "source": [
    "workflow.add_edge(\"retrieve\", \"grade_documents\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 220,
   "id": "4c9aa088-c57d-46eb-b422-cfbf24e52527",
   "metadata": {},
   "outputs": [],
   "source": [
    "workflow.add_conditional_edges(\n",
    "    \"grade_documents\",\n",
    "    decide_to_generate,\n",
    "    {\n",
    "        \"transform_query2doc\": \"transform_query2doc\",\n",
    "        \"generate\": \"generate\",\n",
    "    },\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 221,
   "id": "62be2d9a-97b3-4b5c-a500-818e12be21d9",
   "metadata": {},
   "outputs": [],
   "source": [
    "workflow.add_edge(\"transform_query2doc\", \"retrieve\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 222,
   "id": "f4196466-9d9c-49b8-918b-a6a497bff011",
   "metadata": {},
   "outputs": [],
   "source": [
    "workflow.add_conditional_edges(\n",
    "    \"generate\",\n",
    "    grade_generation_v_documents_and_question,\n",
    "    {\n",
    "        \"not supported\": END,\n",
    "        \"useful\": END,\n",
    "        \"end\": END,\n",
    "        \"not useful\": \"transform_query_rewrite\",\n",
    "    },\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 223,
   "id": "57c75218-5836-48a8-99f1-aa816f387be7",
   "metadata": {},
   "outputs": [],
   "source": [
    "workflow.add_edge(\"transform_query_rewrite\", \"retrieve\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 224,
   "id": "d0ab07fc-3f27-473d-b2b9-6b2f73eca4c1",
   "metadata": {},
   "outputs": [],
   "source": [
    "app = workflow.compile()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 225,
   "id": "1a91c996-5024-4146-a446-082f9d56bdc2",
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"那个，我们公司有什么规定来着？\"\n",
    "inputs = {\"keys\": {\"question\": query}}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 226,
   "id": "3686d6b1-3e43-4615-adf6-6971dcc37680",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "---retrieve---\n",
      "---Determines whether the retrieved documents are relevant to the question---\n",
      "---GRADE: DOCUMENT RELEVANT---\n",
      "---GRADE: DOCUMENT NOT RELEVANT---\n",
      "---GRADE: DOCUMENT NOT RELEVANT---\n",
      "---DECIDE TO GENERATE---\n",
      "---DECISION:  transform_query2doc---\n",
      "---transform_query2doc---\n",
      "#################### query2doc\n",
      "那个，我们公司有什么规定来着？, 您公司的具体规定会根据所在国家或地区的法律法规以及公司自身的管理需求而定。通常包括但不限于：\n",
      "\n",
      "1. **工作时间与休息**：明确标准工时、加班政策及休假安排。\n",
      "2. **薪酬福利**：工资发放周期、奖金制度、保险和退休金计划等。\n",
      "3. **行为准则**：职业道德规范，如禁止歧视、骚扰，要求诚实守信等。\n",
      "4. **保密协议**：保护公司商业秘密和个人隐私的规定。\n",
      "5. **健康与安全**：工作场所的安全规定及紧急情况应对措施。\n",
      "6. **绩效评估**：员工表现评价标准和流程。\n",
      "7. **培训与发展**：提供职业发展机会和支持的政策。\n",
      "\n",
      "具体细节请参考您公司的员工手册或向人力资源部门咨询。每家公司的情况不同，上述仅为一般性概述。\n",
      "#################### query2doc\n",
      "---retrieve---\n",
      "---Determines whether the retrieved documents are relevant to the question---\n",
      "---GRADE: DOCUMENT RELEVANT---\n",
      "---GRADE: DOCUMENT NOT RELEVANT---\n",
      "---GRADE: DOCUMENT RELEVANT---\n",
      "---DECIDE TO GENERATE---\n",
      "---DECISION: GENERATE---\n",
      "---Generate answer---\n",
      "---Determines whether the answer is relevant to the question---\n",
      "---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---\n",
      "---GRADE GENERATION vs QUESTION---\n",
      "---DECISION: GENERATION ADDRESSES QUESTION---\n"
     ]
    }
   ],
   "source": [
    "for output in app.stream(inputs):\n",
    "    for key, value in output.items():\n",
    "        pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 227,
   "id": "1c349521-678a-4281-af11-863051ffab8d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "公司规定包括加班需提前申请并有打卡记录，无打卡记录的加班不计时长。加班费按实际加班时间的2倍计算，或以调休形式返还。请假遇紧急情况可口头申请，但需在上班后两天内补办手续，否则按旷工处理。迟到、早退和未经批准离岗视为旷工，并按照相关办法进行处理。\n"
     ]
    }
   ],
   "source": [
    "print(output['generate']['keys']['generation'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7aed4522-a761-4f78-8b97-530306299e5d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 228,
   "id": "f7c99d37-2bbc-464f-ad8a-6b3dd94c284c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "---retrieve---\n",
      "---Determines whether the retrieved documents are relevant to the question---\n",
      "---GRADE: DOCUMENT NOT RELEVANT---\n",
      "---GRADE: DOCUMENT RELEVANT---\n",
      "---GRADE: DOCUMENT NOT RELEVANT---\n",
      "---DECIDE TO GENERATE---\n",
      "---DECISION:  transform_query2doc---\n",
      "---transform_query2doc---\n",
      "#################### query2doc\n",
      "病假要提交什么材料?, 病假申请通常需要提交以下材料：\n",
      "\n",
      "1. 医疗机构出具的诊断证明或病假条，上面应有医生签名和医院公章。\n",
      "2. 就诊记录、处方单或其他医疗文件（如果有的话）。\n",
      "\n",
      "请根据公司具体要求准备相关材料，并及时通知直接上级及人力资源部门。不同公司可能有不同的规定，请参照本公司员工手册或向HR咨询详细要求。\n",
      "#################### query2doc\n",
      "---retrieve---\n",
      "---Determines whether the retrieved documents are relevant to the question---\n",
      "---GRADE: DOCUMENT NOT RELEVANT---\n",
      "---GRADE: DOCUMENT NOT RELEVANT---\n",
      "---GRADE: DOCUMENT NOT RELEVANT---\n",
      "---DECIDE TO GENERATE---\n",
      "---DECISION: GENERATE---\n",
      "---Generate answer---\n",
      "---Determines whether the answer is relevant to the question---\n",
      "---DECISION: GENERATION IS GROUNDED IN DOCUMENTS---\n",
      "---GRADE GENERATION vs QUESTION---\n",
      "---DECISION: GENERATION ADDRESSES QUESTION---\n"
     ]
    }
   ],
   "source": [
    "query = \"病假要提交什么材料?\"\n",
    "inputs = {\"keys\": {\"question\": query}}\n",
    "for output in app.stream(inputs):\n",
    "    for key, value in output.items():\n",
    "        pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 229,
   "id": "4523566c-29b6-4501-a51d-f17679fa8fca",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "根据我们公司的规定，申请病假时，您需要提交以下材料：\n",
      "\n",
      "1. 病历或诊断证明书：由医院出具的正式文件，上面应有医生签名和医院盖章。\n",
      "2. 就诊记录：包括挂号单、检查报告等就诊过程中的相关资料。\n",
      "3. 请假条：请在公司内部系统中填写并提交电子版请假申请。\n",
      "\n",
      "请注意，具体要求可能因病假天数的不同而有所差异。如果您的病假超过三天，请确保提供完整的医疗证明材料。如有任何疑问，欢迎随时与人力资源部门联系。\n"
     ]
    }
   ],
   "source": [
    "print(output['generate']['keys']['generation'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dbd2161b-4a7e-4e92-aeb0-e32957618a10",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "llm",
   "language": "python",
   "name": "llm"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
